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 const char vlc_module_name
[] = "test_http_msg";
39 static void check_req(const struct vlc_http_msg
*m
)
43 assert(vlc_http_msg_get_status(m
) < 0);
44 str
= vlc_http_msg_get_method(m
);
45 assert(str
!= NULL
&& !strcmp(str
, "GET"));
46 str
= vlc_http_msg_get_scheme(m
);
47 assert(str
!= NULL
&& !strcmp(str
, "http"));
48 str
= vlc_http_msg_get_authority(m
);
49 assert(str
!= NULL
&& !strcmp(str
, "www.example.com"));
50 str
= vlc_http_msg_get_path(m
);
51 assert(str
!= NULL
&& !strcmp(str
, "/"));
52 assert(vlc_http_msg_get_size(m
) == 0);
54 str
= vlc_http_msg_get_header(m
, "Cache-Control");
55 assert(str
!= NULL
&& !strcmp(str
, "no-cache"));
56 str
= vlc_http_msg_get_header(m
, "Custom-Key");
57 assert(str
!= NULL
&& !strcmp(str
, "custom-value"));
59 str
= vlc_http_msg_get_header(m
, "Date");
63 static void check_resp(const struct vlc_http_msg
*m
)
67 assert(vlc_http_msg_get_status(m
) == 200);
68 str
= vlc_http_msg_get_method(m
);
70 str
= vlc_http_msg_get_scheme(m
);
72 str
= vlc_http_msg_get_authority(m
);
74 str
= vlc_http_msg_get_path(m
);
77 str
= vlc_http_msg_get_header(m
, "Cache-Control");
78 assert(str
!= NULL
&& !strcmp(str
, "private"));
79 str
= vlc_http_msg_get_header(m
, "Date");
80 assert(str
!= NULL
&& !strcmp(str
, "Mon, 21 Oct 2013 20:13:22 GMT"));
81 str
= vlc_http_msg_get_header(m
, "Location");
82 assert(str
!= NULL
&& !strcmp(str
, "https://www.example.com"));
83 str
= vlc_http_msg_get_header(m
, "Content-Encoding");
84 assert(str
!= NULL
&& !strcmp(str
, "gzip"));
85 str
= vlc_http_msg_get_header(m
, "Set-Cookie");
86 assert(str
!= NULL
&& !strcmp(str
, "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; "
87 "max-age=3600; version=1"));
89 str
= vlc_http_msg_get_header(m
, "Custom-Key");
93 static void check_connect(const struct vlc_http_msg
*m
)
97 assert(vlc_http_msg_get_status(m
) < 0);
98 str
= vlc_http_msg_get_method(m
);
99 assert(str
!= NULL
&& !strcmp(str
, "CONNECT"));
100 str
= vlc_http_msg_get_scheme(m
);
102 str
= vlc_http_msg_get_authority(m
);
103 assert(str
!= NULL
&& !strcmp(str
, "www.example.com"));
104 str
= vlc_http_msg_get_path(m
);
107 str
= vlc_http_msg_get_header(m
, "Custom-Key");
111 static void check_msg(struct vlc_http_msg
*in
,
112 void (*cb
)(const struct vlc_http_msg
*))
114 struct vlc_http_msg
*out
;
120 m1
= vlc_http_msg_format(in
, &len
, false, true);
122 assert(strlen(m1
) == len
);
123 out
= vlc_http_msg_headers(m1
);
124 fprintf(stderr
, "%s", m1
);
126 /* XXX: request parsing not implemented/needed yet */
127 if (vlc_http_msg_get_status(in
) >= 0)
131 vlc_http_msg_destroy(out
);
134 out
= (struct vlc_http_msg
*)vlc_http_msg_h2_frame(in
, 1, true);
137 assert(vlc_http_msg_read(out
) == NULL
);
138 vlc_http_msg_destroy(out
);
141 vlc_http_msg_destroy(in
);
144 static time_t parse_date(const char *str
)
146 struct vlc_http_msg
*m
;
149 m
= vlc_http_req_create("GET", "http", "www.example.com", "/");
151 assert(vlc_http_msg_add_header(m
, "Date", "%s", str
) == 0);
152 t1
= vlc_http_msg_get_atime(m
);
153 assert(vlc_http_msg_add_header(m
, "Last-Modified", "%s", str
) == 0);
154 t2
= vlc_http_msg_get_mtime(m
);
155 assert(vlc_http_msg_get_retry_after(m
) == 0);
156 assert(vlc_http_msg_add_header(m
, "Retry-After", "%s", str
) == 0);
157 vlc_http_msg_get_retry_after(m
);
158 vlc_http_msg_destroy(m
);
164 static const char *check_realm(const char *line
, const char *realm
)
166 struct vlc_http_msg
*m
;
169 m
= vlc_http_resp_create(401);
171 assert(vlc_http_msg_add_header(m
, "WWW-Authenticate", "%s", line
) == 0);
172 value
= vlc_http_msg_get_basic_realm(m
);
174 assert(value
== NULL
);
177 assert(value
!= NULL
);
178 assert(!strcmp(value
, realm
));
181 vlc_http_msg_destroy(m
);
187 struct vlc_http_msg
*m
;
191 /* Formatting and parsing */
192 m
= vlc_http_req_create("GET", "http", "www.example.com", "/");
194 ret
= vlc_http_msg_add_header(m
, "Cache-Control", "no-cache");
196 vlc_http_msg_add_header(m
, "Custom-Key", "%s", "custom-value");
198 check_msg(m
, check_req
);
200 m
= vlc_http_resp_create(200);
202 ret
= vlc_http_msg_add_header(m
, "cache-control", "private");
204 ret
= vlc_http_msg_add_header(m
, "date", "Mon, 21 Oct 2013 20:13:22 GMT");
206 ret
= vlc_http_msg_add_header(m
, "location", "https://www.example.com");
208 ret
= vlc_http_msg_add_header(m
, "content-encoding", "gzip");
210 ret
= vlc_http_msg_add_header(m
, "set-cookie", "foo=%s; max-age=%u; "
211 "version=%u", "ASDJKHQKBZXOQWEOPIUAXQWEOIU",
214 check_msg(m
, check_resp
);
216 m
= vlc_http_req_create("CONNECT", NULL
, "www.example.com", NULL
);
218 check_msg(m
, check_connect
);
221 assert(parse_date("Sun, 06 Nov 1994 08:49:37 GMT") == 784111777);
222 assert(parse_date("Sunday, 06-Nov-94 08:49:37 GMT") == 784111777);
223 assert(parse_date("Sun Nov 6 08:49:37 1994") == 784111777);
224 assert(parse_date("Sunday, 06-Nov-14 08:49:37 GMT") == 1415263777);
225 assert(parse_date("Sun, 06 Bug 1994 08:49:37 GMT") == -1);
226 assert(parse_date("bogus") == -1);
228 assert(check_realm("Basic realm=\"kingdom\"", "kingdom"));
229 assert(check_realm("BaSiC REALM= \"kingdom\"", "kingdom"));
230 assert(check_realm("basic Realm\t=\"kingdom\"", "kingdom"));
231 assert(check_realm("Basic charset=\"utf-8\", realm=\"kingdom\"",
233 assert(check_realm("Basic realm=\"Realm is \\\"Hello world!\\\"\"",
234 "Realm is \"Hello world!\""));
235 assert(check_realm("Basic", NULL
) == NULL
);
237 m
= vlc_http_req_create("PRI", "https", "*", NULL
);
240 assert(vlc_http_msg_add_agent(m
, "Foo") == 0);
241 assert(vlc_http_msg_add_agent(m
, "Foo/1.0") == 0);
242 assert(vlc_http_msg_add_agent(m
, "Foo/1.0 (Hello world) Bar/2.3") == 0);
243 assert(vlc_http_msg_add_agent(m
, "Foo/1.0 (compatible (\\(!))") == 0);
245 assert(vlc_http_msg_add_atime(m
) == 0);
246 time_t t
= vlc_http_msg_get_atime(m
);
247 assert(t
!= (time_t)-1);
248 assert(vlc_http_msg_add_time(m
, "Last-Modified", &t
) == 0);
249 assert(t
== vlc_http_msg_get_mtime(m
));
251 assert(vlc_http_msg_add_creds_basic(m
, false,
252 "Aladdin", "open sesame") == 0);
253 assert(vlc_http_msg_add_creds_basic(m
, true, "test", "123£") == 0);
254 str
= vlc_http_msg_get_header(m
, "Authorization");
255 assert(str
!= NULL
&& !strcmp(str
, "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="));
256 str
= vlc_http_msg_get_header(m
, "Proxy-Authorization");
257 assert(str
!= NULL
&& !strcmp(str
, "Basic dGVzdDoxMjPCow=="));
259 vlc_http_msg_add_header(m
, "Content-Length", "1234");
260 assert(vlc_http_msg_get_size(m
) == 1234);
263 vlc_http_msg_add_header(m
, "X-Folded", "Hello\n\tworld!");
264 str
= vlc_http_msg_get_header(m
, "x-folded");
265 assert(str
!= NULL
&& !strcmp(str
, "Hello \tworld!"));
267 vlc_http_msg_add_header(m
, "TE", "gzip");
268 vlc_http_msg_add_header(m
, "TE", "deflate");
269 vlc_http_msg_add_header(m
, "Pragma", " features=\"broadcast,playlist\"");
270 vlc_http_msg_add_header(m
, "Pragma", " client-id=123456789 ");
271 vlc_http_msg_add_header(m
, "Pragma", "evulz=\"foo \\\"\\ bar\"");
272 vlc_http_msg_add_header(m
, "Pragma", "no-cache ");
274 str
= vlc_http_msg_get_header(m
, "TE");
275 assert(str
!= NULL
&& !strcmp(str
, "gzip, deflate"));
276 str
= vlc_http_msg_get_token(m
, "TE", "gzip");
277 assert(str
!= NULL
&& !strncmp(str
, "gzip", 4));
278 str
= vlc_http_msg_get_token(m
, "TE", "deflate");
279 assert(str
!= NULL
&& !strncmp(str
, "deflate", 7));
280 str
= vlc_http_msg_get_token(m
, "TE", "compress");
282 str
= vlc_http_msg_get_token(m
, "TE", "zip");
284 str
= vlc_http_msg_get_token(m
, "TE", "late");
286 str
= vlc_http_msg_get_token(m
, "Accept-Encoding", "gzip");
288 str
= vlc_http_msg_get_token(m
, "Pragma", "features");
289 assert(str
!= NULL
&& !strncmp(str
, "features=\"", 10));
290 str
= vlc_http_msg_get_token(m
, "Pragma", "broadcast");
292 str
= vlc_http_msg_get_token(m
, "Pragma", "playlist");
294 str
= vlc_http_msg_get_token(m
, "Pragma", "client-id");
295 assert(str
!= NULL
&& !strncmp(str
, "client-id=", 10));
296 str
= vlc_http_msg_get_token(m
, "Pragma", "123456789");
298 str
= vlc_http_msg_get_token(m
, "Pragma", "no-cache");
299 assert(str
!= NULL
&& !strcmp(str
, "no-cache"));
301 vlc_http_msg_add_header(m
, "Cookie", "a=1");
302 vlc_http_msg_add_header(m
, "Cookie", "b=2");
303 str
= vlc_http_msg_get_header(m
, "Cookie");
304 assert(str
!= NULL
&& !strcmp(str
, "a=1; b=2"));
307 assert(vlc_http_msg_add_header(m
, "/naughty", "header") == -1);
308 assert(vlc_http_msg_add_header(m
, "", "void") == -1);
310 assert(vlc_http_msg_add_agent(m
, "") != 0);
311 assert(vlc_http_msg_add_agent(m
, "/1.0") != 0);
312 assert(vlc_http_msg_add_agent(m
, "Bad/1.0\"") != 0);
313 assert(vlc_http_msg_add_agent(m
, "Bad/1.0 (\\)") != 0);
314 assert(vlc_http_msg_add_agent(m
, "Bad/1.0 (\\\x08)") != 0);
315 assert(vlc_http_msg_add_agent(m
, "Bad/1.0 \"Evil\"") != 0);
316 assert(vlc_http_msg_add_agent(m
, "(Hello world)") != 0);
318 assert(vlc_http_msg_add_creds_basic(m
, false, "User:name", "12345") != 0);
319 assert(vlc_http_msg_add_creds_basic(m
, false, "Alice\nand\nbob", "") != 0);
320 assert(vlc_http_msg_add_creds_basic(m
, false, "john", "asdfg\x7f") != 0);
322 vlc_http_msg_destroy(m
);
324 const char *bad1
[][2] = {
325 { ":status", "200" },
326 { ":status", "200" },
327 { "Server", "BigBad/1.0" },
330 m
= vlc_http_msg_h2_headers(3, bad1
);
333 /* HTTP 1.x parser error cases */
334 assert(vlc_http_msg_headers("") == NULL
);
335 assert(vlc_http_msg_headers("\r\n") == NULL
);
336 assert(vlc_http_msg_headers("HTTP/1.1 200 OK") == NULL
);
337 assert(vlc_http_msg_headers("HTTP/1.1 200 OK\r\nH: V\r\n") == NULL
);
338 assert(vlc_http_msg_headers("HTTP/1.1 200 OK\r\n"
339 ":status: 200\r\n\r\n") == NULL
);
340 assert(vlc_http_msg_headers("HTTP/1.1 200 OK\r\n"
341 "/naughty: invalid\r\n\r\n") == NULL
);
346 /* Callback for vlc_http_msg_h2_frame */
347 struct vlc_h2_frame
*
348 vlc_h2_frame_headers(uint_fast32_t id
, uint_fast32_t mtu
, bool eos
,
349 unsigned count
, const char *const tab
[][2])
351 struct vlc_http_msg
*m
;
354 assert(mtu
== VLC_H2_DEFAULT_MAX_FRAME
);
357 const char *headers
[VLC_H2_MAX_HEADERS
][2];
359 for (unsigned i
= 0; i
< count
; i
++)
361 headers
[i
][0] = tab
[i
][0];
362 headers
[i
][1] = tab
[i
][1];
365 m
= vlc_http_msg_h2_headers(count
, headers
);
366 return (struct vlc_h2_frame
*)m
; /* gruik */