1 /*****************************************************************************
2 * message_test.c: HTTP request/response test
3 *****************************************************************************
4 * Copyright (C) 2015 Rémi Denis-Courmont
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
33 #include <vlc_common.h>
37 static void check_req(const struct vlc_http_msg
*m
)
41 assert(vlc_http_msg_get_status(m
) < 0);
42 str
= vlc_http_msg_get_method(m
);
43 assert(str
!= NULL
&& !strcmp(str
, "GET"));
44 str
= vlc_http_msg_get_scheme(m
);
45 assert(str
!= NULL
&& !strcmp(str
, "http"));
46 str
= vlc_http_msg_get_authority(m
);
47 assert(str
!= NULL
&& !strcmp(str
, "www.example.com"));
48 str
= vlc_http_msg_get_path(m
);
49 assert(str
!= NULL
&& !strcmp(str
, "/"));
50 assert(vlc_http_msg_get_size(m
) == 0);
52 str
= vlc_http_msg_get_header(m
, "Cache-Control");
53 assert(str
!= NULL
&& !strcmp(str
, "no-cache"));
54 str
= vlc_http_msg_get_header(m
, "Custom-Key");
55 assert(str
!= NULL
&& !strcmp(str
, "custom-value"));
57 str
= vlc_http_msg_get_header(m
, "Date");
61 static void check_resp(const struct vlc_http_msg
*m
)
65 assert(vlc_http_msg_get_status(m
) == 200);
66 str
= vlc_http_msg_get_method(m
);
68 str
= vlc_http_msg_get_scheme(m
);
70 str
= vlc_http_msg_get_authority(m
);
72 str
= vlc_http_msg_get_path(m
);
75 str
= vlc_http_msg_get_header(m
, "Cache-Control");
76 assert(str
!= NULL
&& !strcmp(str
, "private"));
77 str
= vlc_http_msg_get_header(m
, "Date");
78 assert(str
!= NULL
&& !strcmp(str
, "Mon, 21 Oct 2013 20:13:22 GMT"));
79 str
= vlc_http_msg_get_header(m
, "Location");
80 assert(str
!= NULL
&& !strcmp(str
, "https://www.example.com"));
81 str
= vlc_http_msg_get_header(m
, "Content-Encoding");
82 assert(str
!= NULL
&& !strcmp(str
, "gzip"));
83 str
= vlc_http_msg_get_header(m
, "Set-Cookie");
84 assert(str
!= NULL
&& !strcmp(str
, "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; "
85 "max-age=3600; version=1"));
87 str
= vlc_http_msg_get_header(m
, "Custom-Key");
91 static void check_connect(const struct vlc_http_msg
*m
)
95 assert(vlc_http_msg_get_status(m
) < 0);
96 str
= vlc_http_msg_get_method(m
);
97 assert(str
!= NULL
&& !strcmp(str
, "CONNECT"));
98 str
= vlc_http_msg_get_scheme(m
);
100 str
= vlc_http_msg_get_authority(m
);
101 assert(str
!= NULL
&& !strcmp(str
, "www.example.com"));
102 str
= vlc_http_msg_get_path(m
);
105 str
= vlc_http_msg_get_header(m
, "Custom-Key");
109 static void check_msg(struct vlc_http_msg
*in
,
110 void (*cb
)(const struct vlc_http_msg
*))
112 struct vlc_http_msg
*out
;
118 m1
= vlc_http_msg_format(in
, &len
, false);
120 assert(strlen(m1
) == len
);
121 out
= vlc_http_msg_headers(m1
);
122 fprintf(stderr
, "%s", m1
);
124 /* XXX: request parsing not implemented/needed yet */
125 if (vlc_http_msg_get_status(in
) >= 0)
129 vlc_http_msg_destroy(out
);
132 out
= (struct vlc_http_msg
*)vlc_http_msg_h2_frame(in
, 1, true);
135 assert(vlc_http_msg_read(out
) == NULL
);
136 vlc_http_msg_destroy(out
);
139 vlc_http_msg_destroy(in
);
142 static time_t parse_date(const char *str
)
144 struct vlc_http_msg
*m
;
147 m
= vlc_http_req_create("GET", "http", "www.example.com", "/");
149 assert(vlc_http_msg_add_header(m
, "Date", "%s", str
) == 0);
150 t1
= vlc_http_msg_get_atime(m
);
151 assert(vlc_http_msg_add_header(m
, "Last-Modified", "%s", str
) == 0);
152 t2
= vlc_http_msg_get_mtime(m
);
153 assert(vlc_http_msg_get_retry_after(m
) == 0);
154 assert(vlc_http_msg_add_header(m
, "Retry-After", "%s", str
) == 0);
155 vlc_http_msg_get_retry_after(m
);
156 vlc_http_msg_destroy(m
);
162 static const char *check_realm(const char *line
, const char *realm
)
164 struct vlc_http_msg
*m
;
167 m
= vlc_http_resp_create(401);
169 assert(vlc_http_msg_add_header(m
, "WWW-Authenticate", "%s", line
) == 0);
170 value
= vlc_http_msg_get_basic_realm(m
);
172 assert(value
== NULL
);
175 assert(value
!= NULL
);
176 assert(!strcmp(value
, realm
));
179 vlc_http_msg_destroy(m
);
185 struct vlc_http_msg
*m
;
189 /* Formatting and parsing */
190 m
= vlc_http_req_create("GET", "http", "www.example.com", "/");
192 ret
= vlc_http_msg_add_header(m
, "Cache-Control", "no-cache");
194 vlc_http_msg_add_header(m
, "Custom-Key", "%s", "custom-value");
196 check_msg(m
, check_req
);
198 m
= vlc_http_resp_create(200);
200 ret
= vlc_http_msg_add_header(m
, "cache-control", "private");
202 ret
= vlc_http_msg_add_header(m
, "date", "Mon, 21 Oct 2013 20:13:22 GMT");
204 ret
= vlc_http_msg_add_header(m
, "location", "https://www.example.com");
206 ret
= vlc_http_msg_add_header(m
, "content-encoding", "gzip");
208 ret
= vlc_http_msg_add_header(m
, "set-cookie", "foo=%s; max-age=%u; "
209 "version=%u", "ASDJKHQKBZXOQWEOPIUAXQWEOIU",
212 check_msg(m
, check_resp
);
214 m
= vlc_http_req_create("CONNECT", NULL
, "www.example.com", NULL
);
216 check_msg(m
, check_connect
);
219 assert(parse_date("Sun, 06 Nov 1994 08:49:37 GMT") == 784111777);
220 assert(parse_date("Sunday, 06-Nov-94 08:49:37 GMT") == 784111777);
221 assert(parse_date("Sun Nov 6 08:49:37 1994") == 784111777);
222 assert(parse_date("Sunday, 06-Nov-14 08:49:37 GMT") == 1415263777);
223 assert(parse_date("Sun, 06 Bug 1994 08:49:37 GMT") == -1);
224 assert(parse_date("bogus") == -1);
226 assert(check_realm("Basic realm=\"kingdom\"", "kingdom"));
227 assert(check_realm("BaSiC REALM= \"kingdom\"", "kingdom"));
228 assert(check_realm("basic Realm\t=\"kingdom\"", "kingdom"));
229 assert(check_realm("Basic charset=\"utf-8\", realm=\"kingdom\"",
231 assert(check_realm("Basic realm=\"Realm is \\\"Hello world!\\\"\"",
232 "Realm is \"Hello world!\""));
233 assert(check_realm("Basic", NULL
) == NULL
);
235 m
= vlc_http_req_create("PRI", "https", "*", NULL
);
238 assert(vlc_http_msg_add_agent(m
, "Foo") == 0);
239 assert(vlc_http_msg_add_agent(m
, "Foo/1.0") == 0);
240 assert(vlc_http_msg_add_agent(m
, "Foo/1.0 (Hello world) Bar/2.3") == 0);
241 assert(vlc_http_msg_add_agent(m
, "Foo/1.0 (compatible (\\(!))") == 0);
243 assert(vlc_http_msg_add_atime(m
) == 0);
244 time_t t
= vlc_http_msg_get_atime(m
);
245 assert(t
!= (time_t)-1);
246 assert(vlc_http_msg_add_time(m
, "Last-Modified", &t
) == 0);
247 assert(t
== vlc_http_msg_get_mtime(m
));
249 assert(vlc_http_msg_add_creds_basic(m
, false,
250 "Aladdin", "open sesame") == 0);
251 assert(vlc_http_msg_add_creds_basic(m
, true, "test", "123£") == 0);
252 str
= vlc_http_msg_get_header(m
, "Authorization");
253 assert(str
!= NULL
&& !strcmp(str
, "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="));
254 str
= vlc_http_msg_get_header(m
, "Proxy-Authorization");
255 assert(str
!= NULL
&& !strcmp(str
, "Basic dGVzdDoxMjPCow=="));
257 vlc_http_msg_add_header(m
, "Content-Length", "1234");
258 assert(vlc_http_msg_get_size(m
) == 1234);
261 vlc_http_msg_add_header(m
, "X-Folded", "Hello\n\tworld!");
262 str
= vlc_http_msg_get_header(m
, "x-folded");
263 assert(str
!= NULL
&& !strcmp(str
, "Hello \tworld!"));
265 vlc_http_msg_add_header(m
, "TE", "gzip");
266 vlc_http_msg_add_header(m
, "TE", "deflate");
267 vlc_http_msg_add_header(m
, "Pragma", " features=\"broadcast,playlist\"");
268 vlc_http_msg_add_header(m
, "Pragma", " client-id=123456789 ");
269 vlc_http_msg_add_header(m
, "Pragma", "evulz=\"foo \\\"\\ bar\"");
270 vlc_http_msg_add_header(m
, "Pragma", "no-cache ");
272 str
= vlc_http_msg_get_header(m
, "TE");
273 assert(str
!= NULL
&& !strcmp(str
, "gzip, deflate"));
274 str
= vlc_http_msg_get_token(m
, "TE", "gzip");
275 assert(str
!= NULL
&& !strncmp(str
, "gzip", 4));
276 str
= vlc_http_msg_get_token(m
, "TE", "deflate");
277 assert(str
!= NULL
&& !strncmp(str
, "deflate", 7));
278 str
= vlc_http_msg_get_token(m
, "TE", "compress");
280 str
= vlc_http_msg_get_token(m
, "TE", "zip");
282 str
= vlc_http_msg_get_token(m
, "TE", "late");
284 str
= vlc_http_msg_get_token(m
, "Accept-Encoding", "gzip");
286 str
= vlc_http_msg_get_token(m
, "Pragma", "features");
287 assert(str
!= NULL
&& !strncmp(str
, "features=\"", 10));
288 str
= vlc_http_msg_get_token(m
, "Pragma", "broadcast");
290 str
= vlc_http_msg_get_token(m
, "Pragma", "playlist");
292 str
= vlc_http_msg_get_token(m
, "Pragma", "client-id");
293 assert(str
!= NULL
&& !strncmp(str
, "client-id=", 10));
294 str
= vlc_http_msg_get_token(m
, "Pragma", "123456789");
296 str
= vlc_http_msg_get_token(m
, "Pragma", "no-cache");
297 assert(str
!= NULL
&& !strcmp(str
, "no-cache"));
299 vlc_http_msg_add_header(m
, "Cookie", "a=1");
300 vlc_http_msg_add_header(m
, "Cookie", "b=2");
301 str
= vlc_http_msg_get_header(m
, "Cookie");
302 assert(str
!= NULL
&& !strcmp(str
, "a=1; b=2"));
305 assert(vlc_http_msg_add_header(m
, "/naughty", "header") == -1);
306 assert(vlc_http_msg_add_header(m
, "", "void") == -1);
308 assert(vlc_http_msg_add_agent(m
, "") != 0);
309 assert(vlc_http_msg_add_agent(m
, "/1.0") != 0);
310 assert(vlc_http_msg_add_agent(m
, "Bad/1.0\"") != 0);
311 assert(vlc_http_msg_add_agent(m
, "Bad/1.0 (\\)") != 0);
312 assert(vlc_http_msg_add_agent(m
, "Bad/1.0 (\\\x08)") != 0);
313 assert(vlc_http_msg_add_agent(m
, "Bad/1.0 \"Evil\"") != 0);
314 assert(vlc_http_msg_add_agent(m
, "(Hello world)") != 0);
316 assert(vlc_http_msg_add_creds_basic(m
, false, "User:name", "12345") != 0);
317 assert(vlc_http_msg_add_creds_basic(m
, false, "Alice\nand\nbob", "") != 0);
318 assert(vlc_http_msg_add_creds_basic(m
, false, "john", "asdfg\x7f") != 0);
320 vlc_http_msg_destroy(m
);
322 const char *bad1
[][2] = {
323 { ":status", "200" },
324 { ":status", "200" },
325 { "Server", "BigBad/1.0" },
328 m
= vlc_http_msg_h2_headers(3, bad1
);
331 /* HTTP 1.x parser error cases */
332 assert(vlc_http_msg_headers("") == NULL
);
333 assert(vlc_http_msg_headers("\r\n") == NULL
);
334 assert(vlc_http_msg_headers("HTTP/1.1 200 OK") == NULL
);
335 assert(vlc_http_msg_headers("HTTP/1.1 200 OK\r\nH: V\r\n") == NULL
);
336 assert(vlc_http_msg_headers("HTTP/1.1 200 OK\r\n"
337 ":status: 200\r\n\r\n") == NULL
);
338 assert(vlc_http_msg_headers("HTTP/1.1 200 OK\r\n"
339 "/naughty: invalid\r\n\r\n") == NULL
);
344 /* Callback for vlc_http_msg_h2_frame */
345 struct vlc_h2_frame
*
346 vlc_h2_frame_headers(uint_fast32_t id
, uint_fast32_t mtu
, bool eos
,
347 unsigned count
, const char *const tab
[][2])
349 struct vlc_http_msg
*m
;
352 assert(mtu
== VLC_H2_DEFAULT_MAX_FRAME
);
355 const char *headers
[VLC_H2_MAX_HEADERS
][2];
357 for (unsigned i
= 0; i
< count
; i
++)
359 headers
[i
][0] = tab
[i
][0];
360 headers
[i
][1] = tab
[i
][1];
363 m
= vlc_http_msg_h2_headers(count
, headers
);
364 return (struct vlc_h2_frame
*)m
; /* gruik */