blob: f56f48ebdae0ae3254ad2cc1b4c558399265c802 [file] [log] [blame]
[email protected]b1fd7192012-01-31 01:00:491// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
5#include <algorithm>
sclittle0a4f767d2016-12-03 03:45:546#include <limits>
initial.commit586acc5fe2008-07-26 22:42:527
[email protected]125ef482013-06-11 18:32:478#include "base/strings/string_util.h"
initial.commit586acc5fe2008-07-26 22:42:529#include "net/http/http_util.h"
10#include "testing/gtest/include/gtest/gtest.h"
11
ttuttle859dc7a2015-04-23 19:42:2912namespace net {
initial.commit586acc5fe2008-07-26 22:42:5213
14namespace {
15class HttpUtilTest : public testing::Test {};
16}
17
[email protected]8e3ae68c2011-09-16 22:15:4718TEST(HttpUtilTest, IsSafeHeader) {
thestig9d3bb0c2015-01-24 00:49:5119 static const char* const unsafe_headers[] = {
[email protected]8e3ae68c2011-09-16 22:15:4720 "sec-",
21 "sEc-",
22 "sec-foo",
23 "sEc-FoO",
24 "proxy-",
25 "pRoXy-",
26 "proxy-foo",
27 "pRoXy-FoO",
28 "accept-charset",
29 "accept-encoding",
[email protected]48742732012-05-14 18:43:0730 "access-control-request-headers",
31 "access-control-request-method",
[email protected]8e3ae68c2011-09-16 22:15:4732 "connection",
33 "content-length",
34 "cookie",
35 "cookie2",
36 "content-transfer-encoding",
37 "date",
38 "expect",
39 "host",
40 "keep-alive",
41 "origin",
42 "referer",
43 "te",
44 "trailer",
45 "transfer-encoding",
46 "upgrade",
47 "user-agent",
48 "via",
49 };
50 for (size_t i = 0; i < arraysize(unsafe_headers); ++i) {
51 EXPECT_FALSE(HttpUtil::IsSafeHeader(unsafe_headers[i]))
52 << unsafe_headers[i];
brettwc15100c2015-08-06 22:54:1653 EXPECT_FALSE(HttpUtil::IsSafeHeader(base::ToUpperASCII(unsafe_headers[i])))
brettw7622fbed2015-06-09 20:20:1454 << unsafe_headers[i];
[email protected]8e3ae68c2011-09-16 22:15:4755 }
thestig9d3bb0c2015-01-24 00:49:5156 static const char* const safe_headers[] = {
[email protected]8e3ae68c2011-09-16 22:15:4757 "foo",
58 "x-",
59 "x-foo",
60 "content-disposition",
61 "update",
62 "accept-charseta",
63 "accept_charset",
64 "accept-encodinga",
65 "accept_encoding",
[email protected]48742732012-05-14 18:43:0766 "access-control-request-headersa",
67 "access-control-request-header",
68 "access_control_request_header",
69 "access-control-request-methoda",
70 "access_control_request_method",
[email protected]8e3ae68c2011-09-16 22:15:4771 "connectiona",
72 "content-lengtha",
73 "content_length",
74 "cookiea",
75 "cookie2a",
76 "cookie3",
77 "content-transfer-encodinga",
78 "content_transfer_encoding",
79 "datea",
80 "expecta",
81 "hosta",
82 "keep-alivea",
83 "keep_alive",
84 "origina",
85 "referera",
86 "referrer",
87 "tea",
88 "trailera",
89 "transfer-encodinga",
90 "transfer_encoding",
91 "upgradea",
92 "user-agenta",
93 "user_agent",
94 "viaa",
95 };
96 for (size_t i = 0; i < arraysize(safe_headers); ++i) {
97 EXPECT_TRUE(HttpUtil::IsSafeHeader(safe_headers[i])) << safe_headers[i];
brettwc15100c2015-08-06 22:54:1698 EXPECT_TRUE(HttpUtil::IsSafeHeader(base::ToUpperASCII(safe_headers[i])))
brettw7622fbed2015-06-09 20:20:1499 << safe_headers[i];
[email protected]8e3ae68c2011-09-16 22:15:47100 }
101}
102
initial.commit586acc5fe2008-07-26 22:42:52103TEST(HttpUtilTest, HeadersIterator) {
104 std::string headers = "foo: 1\t\r\nbar: hello world\r\nbaz: 3 \r\n";
105
106 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
107
108 ASSERT_TRUE(it.GetNext());
109 EXPECT_EQ(std::string("foo"), it.name());
110 EXPECT_EQ(std::string("1"), it.values());
111
112 ASSERT_TRUE(it.GetNext());
113 EXPECT_EQ(std::string("bar"), it.name());
114 EXPECT_EQ(std::string("hello world"), it.values());
115
116 ASSERT_TRUE(it.GetNext());
117 EXPECT_EQ(std::string("baz"), it.name());
118 EXPECT_EQ(std::string("3"), it.values());
119
120 EXPECT_FALSE(it.GetNext());
121}
122
123TEST(HttpUtilTest, HeadersIterator_MalformedLine) {
124 std::string headers = "foo: 1\n: 2\n3\nbar: 4";
125
126 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n");
127
128 ASSERT_TRUE(it.GetNext());
129 EXPECT_EQ(std::string("foo"), it.name());
130 EXPECT_EQ(std::string("1"), it.values());
131
132 ASSERT_TRUE(it.GetNext());
133 EXPECT_EQ(std::string("bar"), it.name());
134 EXPECT_EQ(std::string("4"), it.values());
135
136 EXPECT_FALSE(it.GetNext());
137}
138
rob78f29ac2016-06-28 17:33:43139TEST(HttpUtilTest, HeadersIterator_MalformedName) {
140 std::string headers = "[ignore me] /: 3\r\n";
141
142 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
143
144 EXPECT_FALSE(it.GetNext());
145}
146
147TEST(HttpUtilTest, HeadersIterator_MalformedNameFollowedByValidLine) {
148 std::string headers = "[ignore me] /: 3\r\nbar: 4\n";
149
150 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
151
152 ASSERT_TRUE(it.GetNext());
153 EXPECT_EQ(std::string("bar"), it.name());
154 EXPECT_EQ(std::string("4"), it.values());
155
156 EXPECT_FALSE(it.GetNext());
157}
158
[email protected]357ff692009-10-16 14:55:19159TEST(HttpUtilTest, HeadersIterator_AdvanceTo) {
160 std::string headers = "foo: 1\r\n: 2\r\n3\r\nbar: 4";
161
162 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
163 EXPECT_TRUE(it.AdvanceTo("foo"));
164 EXPECT_EQ("foo", it.name());
165 EXPECT_TRUE(it.AdvanceTo("bar"));
166 EXPECT_EQ("bar", it.name());
167 EXPECT_FALSE(it.AdvanceTo("blat"));
168 EXPECT_FALSE(it.GetNext()); // should be at end of headers
169}
170
[email protected]cbb7d422009-10-16 21:41:09171TEST(HttpUtilTest, HeadersIterator_Reset) {
172 std::string headers = "foo: 1\r\n: 2\r\n3\r\nbar: 4";
173 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
174 // Search past "foo".
175 EXPECT_TRUE(it.AdvanceTo("bar"));
176 // Now try advancing to "foo". This time it should fail since the iterator
177 // position is past it.
178 EXPECT_FALSE(it.AdvanceTo("foo"));
179 it.Reset();
180 // Now that we reset the iterator position, we should find 'foo'
181 EXPECT_TRUE(it.AdvanceTo("foo"));
182}
183
initial.commit586acc5fe2008-07-26 22:42:52184TEST(HttpUtilTest, ValuesIterator) {
185 std::string values = " must-revalidate, no-cache=\"foo, bar\"\t, private ";
186
187 HttpUtil::ValuesIterator it(values.begin(), values.end(), ',');
188
189 ASSERT_TRUE(it.GetNext());
190 EXPECT_EQ(std::string("must-revalidate"), it.value());
191
192 ASSERT_TRUE(it.GetNext());
193 EXPECT_EQ(std::string("no-cache=\"foo, bar\""), it.value());
194
195 ASSERT_TRUE(it.GetNext());
196 EXPECT_EQ(std::string("private"), it.value());
197
198 EXPECT_FALSE(it.GetNext());
199}
200
201TEST(HttpUtilTest, ValuesIterator_Blanks) {
202 std::string values = " \t ";
203
204 HttpUtil::ValuesIterator it(values.begin(), values.end(), ',');
205
206 EXPECT_FALSE(it.GetNext());
207}
208
[email protected]c3b35c22008-09-27 03:19:42209TEST(HttpUtilTest, Unquote) {
210 // Replace <backslash> " with ".
211 EXPECT_STREQ("xyz\"abc", HttpUtil::Unquote("\"xyz\\\"abc\"").c_str());
212
213 // Replace <backslash> <backslash> with <backslash>
214 EXPECT_STREQ("xyz\\abc", HttpUtil::Unquote("\"xyz\\\\abc\"").c_str());
215 EXPECT_STREQ("xyz\\\\\\abc",
216 HttpUtil::Unquote("\"xyz\\\\\\\\\\\\abc\"").c_str());
217
218 // Replace <backslash> X with X
219 EXPECT_STREQ("xyzXabc", HttpUtil::Unquote("\"xyz\\Xabc\"").c_str());
220
221 // Act as identity function on unquoted inputs.
222 EXPECT_STREQ("X", HttpUtil::Unquote("X").c_str());
223 EXPECT_STREQ("\"", HttpUtil::Unquote("\"").c_str());
224
225 // Allow single quotes to act as quote marks.
226 // Not part of RFC 2616.
227 EXPECT_STREQ("x\"", HttpUtil::Unquote("'x\"'").c_str());
mek9b28f422016-05-13 21:46:23228
229 // Allow quotes in the middle of the input.
230 EXPECT_STREQ("foo\"bar", HttpUtil::Unquote("\"foo\"bar\"").c_str());
231
232 // Allow the final quote to be escaped.
233 EXPECT_STREQ("foo", HttpUtil::Unquote("\"foo\\\"").c_str());
234}
235
236TEST(HttpUtilTest, StrictUnquote) {
237 std::string out;
238
239 // Replace <backslash> " with ".
240 EXPECT_TRUE(HttpUtil::StrictUnquote("\"xyz\\\"abc\"", &out));
241 EXPECT_STREQ("xyz\"abc", out.c_str());
242
243 // Replace <backslash> <backslash> with <backslash>.
244 EXPECT_TRUE(HttpUtil::StrictUnquote("\"xyz\\\\abc\"", &out));
245 EXPECT_STREQ("xyz\\abc", out.c_str());
246 EXPECT_TRUE(HttpUtil::StrictUnquote("\"xyz\\\\\\\\\\\\abc\"", &out));
247 EXPECT_STREQ("xyz\\\\\\abc", out.c_str());
248
249 // Replace <backslash> X with X.
250 EXPECT_TRUE(HttpUtil::StrictUnquote("\"xyz\\Xabc\"", &out));
251 EXPECT_STREQ("xyzXabc", out.c_str());
252
253 // Empty quoted string.
254 EXPECT_TRUE(HttpUtil::StrictUnquote("\"\"", &out));
255 EXPECT_STREQ("", out.c_str());
256
257 // Return false on unquoted inputs.
258 EXPECT_FALSE(HttpUtil::StrictUnquote("X", &out));
259 EXPECT_FALSE(HttpUtil::StrictUnquote("", &out));
260
261 // Return false on mismatched quotes.
262 EXPECT_FALSE(HttpUtil::StrictUnquote("\"", &out));
263 EXPECT_FALSE(HttpUtil::StrictUnquote("\"xyz", &out));
264 EXPECT_FALSE(HttpUtil::StrictUnquote("\"abc'", &out));
265
266 // Return false on escaped terminal quote.
267 EXPECT_FALSE(HttpUtil::StrictUnquote("\"abc\\\"", &out));
268 EXPECT_FALSE(HttpUtil::StrictUnquote("\"\\\"", &out));
269
270 // Allow escaped backslash before terminal quote.
271 EXPECT_TRUE(HttpUtil::StrictUnquote("\"\\\\\"", &out));
272 EXPECT_STREQ("\\", out.c_str());
273
274 // Don't allow single quotes to act as quote marks.
275 EXPECT_FALSE(HttpUtil::StrictUnquote("'x\"'", &out));
276 EXPECT_TRUE(HttpUtil::StrictUnquote("\"x'\"", &out));
277 EXPECT_STREQ("x'", out.c_str());
278 EXPECT_FALSE(HttpUtil::StrictUnquote("''", &out));
[email protected]c3b35c22008-09-27 03:19:42279}
280
281TEST(HttpUtilTest, Quote) {
282 EXPECT_STREQ("\"xyz\\\"abc\"", HttpUtil::Quote("xyz\"abc").c_str());
283
284 // Replace <backslash> <backslash> with <backslash>
285 EXPECT_STREQ("\"xyz\\\\abc\"", HttpUtil::Quote("xyz\\abc").c_str());
286
287 // Replace <backslash> X with X
288 EXPECT_STREQ("\"xyzXabc\"", HttpUtil::Quote("xyzXabc").c_str());
289}
290
initial.commit586acc5fe2008-07-26 22:42:52291TEST(HttpUtilTest, LocateEndOfHeaders) {
292 struct {
thestig9d3bb0c2015-01-24 00:49:51293 const char* const input;
initial.commit586acc5fe2008-07-26 22:42:52294 int expected_result;
295 } tests[] = {
haavardm8e7ed882015-06-11 08:19:54296 {"\r\n", -1},
297 {"\n", -1},
298 {"\r", -1},
299 {"foo", -1},
300 {"\r\n\r\n", 4},
301 {"foo\r\nbar\r\n\r\n", 12},
302 {"foo\nbar\n\n", 9},
303 {"foo\r\nbar\r\n\r\njunk", 12},
304 {"foo\nbar\n\njunk", 9},
305 {"foo\nbar\n\r\njunk", 10},
306 {"foo\nbar\r\n\njunk", 10},
initial.commit586acc5fe2008-07-26 22:42:52307 };
viettrungluue4a8b882014-10-16 06:17:38308 for (size_t i = 0; i < arraysize(tests); ++i) {
initial.commit586acc5fe2008-07-26 22:42:52309 int input_len = static_cast<int>(strlen(tests[i].input));
310 int eoh = HttpUtil::LocateEndOfHeaders(tests[i].input, input_len);
311 EXPECT_EQ(tests[i].expected_result, eoh);
312 }
313}
314
haavardm8e7ed882015-06-11 08:19:54315TEST(HttpUtilTest, LocateEndOfAdditionalHeaders) {
316 struct {
317 const char* const input;
318 int expected_result;
319 } tests[] = {
320 {"\r\n", 2},
321 {"\n", 1},
322 {"\r", -1},
323 {"foo", -1},
324 {"\r\n\r\n", 2},
325 {"foo\r\nbar\r\n\r\n", 12},
326 {"foo\nbar\n\n", 9},
327 {"foo\r\nbar\r\n\r\njunk", 12},
328 {"foo\nbar\n\njunk", 9},
329 {"foo\nbar\n\r\njunk", 10},
330 {"foo\nbar\r\n\njunk", 10},
331 };
332 for (size_t i = 0; i < arraysize(tests); ++i) {
333 int input_len = static_cast<int>(strlen(tests[i].input));
334 int eoh = HttpUtil::LocateEndOfAdditionalHeaders(tests[i].input, input_len);
335 EXPECT_EQ(tests[i].expected_result, eoh);
336 }
337}
initial.commit586acc5fe2008-07-26 22:42:52338TEST(HttpUtilTest, AssembleRawHeaders) {
eromanacf834a52016-12-06 21:13:27339 // clang-format off
initial.commit586acc5fe2008-07-26 22:42:52340 struct {
thestig9d3bb0c2015-01-24 00:49:51341 const char* const input; // with '|' representing '\0'
342 const char* const expected_result; // with '\0' changed to '|'
initial.commit586acc5fe2008-07-26 22:42:52343 } tests[] = {
344 { "HTTP/1.0 200 OK\r\nFoo: 1\r\nBar: 2\r\n\r\n",
345 "HTTP/1.0 200 OK|Foo: 1|Bar: 2||" },
346
347 { "HTTP/1.0 200 OK\nFoo: 1\nBar: 2\n\n",
348 "HTTP/1.0 200 OK|Foo: 1|Bar: 2||" },
[email protected]036d8772008-09-06 01:00:53349
350 // Valid line continuation (single SP).
351 {
352 "HTTP/1.0 200 OK\n"
353 "Foo: 1\n"
354 " continuation\n"
355 "Bar: 2\n\n",
356
357 "HTTP/1.0 200 OK|"
358 "Foo: 1 continuation|"
359 "Bar: 2||"
360 },
361
362 // Valid line continuation (single HT).
363 {
364 "HTTP/1.0 200 OK\n"
365 "Foo: 1\n"
366 "\tcontinuation\n"
367 "Bar: 2\n\n",
368
369 "HTTP/1.0 200 OK|"
[email protected]e9fe92b2008-09-08 20:49:51370 "Foo: 1 continuation|"
[email protected]036d8772008-09-06 01:00:53371 "Bar: 2||"
372 },
373
374 // Valid line continuation (multiple SP).
375 {
376 "HTTP/1.0 200 OK\n"
377 "Foo: 1\n"
378 " continuation\n"
379 "Bar: 2\n\n",
380
381 "HTTP/1.0 200 OK|"
[email protected]e9fe92b2008-09-08 20:49:51382 "Foo: 1 continuation|"
[email protected]036d8772008-09-06 01:00:53383 "Bar: 2||"
384 },
385
386 // Valid line continuation (multiple HT).
387 {
388 "HTTP/1.0 200 OK\n"
389 "Foo: 1\n"
390 "\t\t\tcontinuation\n"
391 "Bar: 2\n\n",
392
393 "HTTP/1.0 200 OK|"
[email protected]e9fe92b2008-09-08 20:49:51394 "Foo: 1 continuation|"
[email protected]036d8772008-09-06 01:00:53395 "Bar: 2||"
396 },
397
398 // Valid line continuation (mixed HT, SP).
399 {
400 "HTTP/1.0 200 OK\n"
401 "Foo: 1\n"
402 " \t \t continuation\n"
403 "Bar: 2\n\n",
404
405 "HTTP/1.0 200 OK|"
[email protected]e9fe92b2008-09-08 20:49:51406 "Foo: 1 continuation|"
[email protected]036d8772008-09-06 01:00:53407 "Bar: 2||"
408 },
409
410 // Valid multi-line continuation
411 {
412 "HTTP/1.0 200 OK\n"
413 "Foo: 1\n"
414 " continuation1\n"
415 "\tcontinuation2\n"
416 " continuation3\n"
417 "Bar: 2\n\n",
418
419 "HTTP/1.0 200 OK|"
[email protected]e9fe92b2008-09-08 20:49:51420 "Foo: 1 continuation1 continuation2 continuation3|"
421 "Bar: 2||"
422 },
423
424 // Continuation of quoted value.
425 // This is different from what Firefox does, since it
426 // will preserve the LWS.
427 {
428 "HTTP/1.0 200 OK\n"
429 "Etag: \"34534-d3\n"
430 " 134q\"\n"
431 "Bar: 2\n\n",
432
433 "HTTP/1.0 200 OK|"
434 "Etag: \"34534-d3 134q\"|"
435 "Bar: 2||"
436 },
437
438 // Valid multi-line continuation, full LWS lines
439 {
440 "HTTP/1.0 200 OK\n"
441 "Foo: 1\n"
442 " \n"
443 "\t\t\t\t\n"
444 "\t continuation\n"
445 "Bar: 2\n\n",
446
447 // One SP per continued line = 3.
448 "HTTP/1.0 200 OK|"
449 "Foo: 1 continuation|"
450 "Bar: 2||"
451 },
452
453 // Valid multi-line continuation, all LWS
454 {
455 "HTTP/1.0 200 OK\n"
456 "Foo: 1\n"
457 " \n"
458 "\t\t\t\t\n"
459 "\t \n"
460 "Bar: 2\n\n",
461
462 // One SP per continued line = 3.
463 "HTTP/1.0 200 OK|"
464 "Foo: 1 |"
[email protected]036d8772008-09-06 01:00:53465 "Bar: 2||"
466 },
467
468 // Valid line continuation (No value bytes in first line).
469 {
470 "HTTP/1.0 200 OK\n"
471 "Foo:\n"
472 " value\n"
473 "Bar: 2\n\n",
474
475 "HTTP/1.0 200 OK|"
476 "Foo: value|"
477 "Bar: 2||"
478 },
479
480 // Not a line continuation (can't continue status line).
481 {
482 "HTTP/1.0 200 OK\n"
483 " Foo: 1\n"
484 "Bar: 2\n\n",
485
486 "HTTP/1.0 200 OK|"
487 " Foo: 1|"
488 "Bar: 2||"
489 },
490
491 // Not a line continuation (can't continue status line).
492 {
493 "HTTP/1.0\n"
494 " 200 OK\n"
495 "Foo: 1\n"
496 "Bar: 2\n\n",
497
498 "HTTP/1.0|"
499 " 200 OK|"
500 "Foo: 1|"
501 "Bar: 2||"
502 },
503
504 // Not a line continuation (can't continue status line).
505 {
506 "HTTP/1.0 404\n"
507 " Not Found\n"
508 "Foo: 1\n"
509 "Bar: 2\n\n",
510
511 "HTTP/1.0 404|"
512 " Not Found|"
513 "Foo: 1|"
514 "Bar: 2||"
515 },
516
517 // Unterminated status line.
518 {
519 "HTTP/1.0 200 OK",
[email protected]fe3d9d772009-01-23 00:39:47520
[email protected]036d8772008-09-06 01:00:53521 "HTTP/1.0 200 OK||"
522 },
523
524 // Single terminated, with headers
525 {
526 "HTTP/1.0 200 OK\n"
527 "Foo: 1\n"
528 "Bar: 2\n",
529
530 "HTTP/1.0 200 OK|"
531 "Foo: 1|"
532 "Bar: 2||"
533 },
534
535 // Not terminated, with headers
536 {
537 "HTTP/1.0 200 OK\n"
538 "Foo: 1\n"
539 "Bar: 2",
540
541 "HTTP/1.0 200 OK|"
542 "Foo: 1|"
543 "Bar: 2||"
544 },
545
546 // Not a line continuation (VT)
547 {
548 "HTTP/1.0 200 OK\n"
549 "Foo: 1\n"
550 "\vInvalidContinuation\n"
551 "Bar: 2\n\n",
552
553 "HTTP/1.0 200 OK|"
554 "Foo: 1|"
555 "\vInvalidContinuation|"
556 "Bar: 2||"
557 },
558
559 // Not a line continuation (formfeed)
560 {
561 "HTTP/1.0 200 OK\n"
562 "Foo: 1\n"
563 "\fInvalidContinuation\n"
564 "Bar: 2\n\n",
565
566 "HTTP/1.0 200 OK|"
567 "Foo: 1|"
568 "\fInvalidContinuation|"
569 "Bar: 2||"
570 },
571
572 // Not a line continuation -- can't continue header names.
573 {
574 "HTTP/1.0 200 OK\n"
575 "Serv\n"
576 " er: Apache\n"
577 "\tInvalidContinuation\n"
578 "Bar: 2\n\n",
579
580 "HTTP/1.0 200 OK|"
581 "Serv|"
582 " er: Apache|"
583 "\tInvalidContinuation|"
584 "Bar: 2||"
585 },
586
587 // Not a line continuation -- no value to continue.
588 {
589 "HTTP/1.0 200 OK\n"
590 "Foo: 1\n"
591 "garbage\n"
592 " not-a-continuation\n"
593 "Bar: 2\n\n",
594
595 "HTTP/1.0 200 OK|"
596 "Foo: 1|"
597 "garbage|"
598 " not-a-continuation|"
599 "Bar: 2||",
600 },
601
602 // Not a line continuation -- no valid name.
603 {
604 "HTTP/1.0 200 OK\n"
605 ": 1\n"
606 " garbage\n"
607 "Bar: 2\n\n",
608
609 "HTTP/1.0 200 OK|"
610 ": 1|"
611 " garbage|"
612 "Bar: 2||",
613 },
614
615 // Not a line continuation -- no valid name (whitespace)
616 {
617 "HTTP/1.0 200 OK\n"
618 " : 1\n"
619 " garbage\n"
620 "Bar: 2\n\n",
621
622 "HTTP/1.0 200 OK|"
623 " : 1|"
624 " garbage|"
625 "Bar: 2||",
626 },
627
[email protected]2bcaf462011-09-13 04:55:18628 // Embed NULLs in the status line. They should not be understood
629 // as line separators.
630 {
631 "HTTP/1.0 200 OK|Bar2:0|Baz2:1\r\nFoo: 1\r\nBar: 2\r\n\r\n",
632 "HTTP/1.0 200 OKBar2:0Baz2:1|Foo: 1|Bar: 2||"
633 },
634
635 // Embed NULLs in a header line. They should not be understood as
636 // line separators.
637 {
638 "HTTP/1.0 200 OK\nFoo: 1|Foo2: 3\nBar: 2\n\n",
639 "HTTP/1.0 200 OK|Foo: 1Foo2: 3|Bar: 2||"
640 },
eromanacf834a52016-12-06 21:13:27641
642 // The embedded NUL at the start of the line (before "Blah:") should not be
643 // interpreted as LWS (as that would mistake it for a header line
644 // continuation).
645 {
646 "HTTP/1.0 200 OK\n"
647 "Foo: 1\n"
648 "|Blah: 3\n"
649 "Bar: 2\n\n",
650 "HTTP/1.0 200 OK|Foo: 1|Blah: 3|Bar: 2||"
651 },
initial.commit586acc5fe2008-07-26 22:42:52652 };
eromanacf834a52016-12-06 21:13:27653 // clang-format on
viettrungluue4a8b882014-10-16 06:17:38654 for (size_t i = 0; i < arraysize(tests); ++i) {
[email protected]2bcaf462011-09-13 04:55:18655 std::string input = tests[i].input;
656 std::replace(input.begin(), input.end(), '|', '\0');
657 std::string raw = HttpUtil::AssembleRawHeaders(input.data(), input.size());
initial.commit586acc5fe2008-07-26 22:42:52658 std::replace(raw.begin(), raw.end(), '\0', '|');
[email protected]2bcaf462011-09-13 04:55:18659 EXPECT_EQ(tests[i].expected_result, raw);
initial.commit586acc5fe2008-07-26 22:42:52660 }
661}
license.botbf09a502008-08-24 00:55:55662
nharper834c49b2015-06-03 23:46:43663// Test SpecForRequest().
[email protected]3130a8532008-09-15 18:37:11664TEST(HttpUtilTest, RequestUrlSanitize) {
665 struct {
thestig9d3bb0c2015-01-24 00:49:51666 const char* const url;
667 const char* const expected_spec;
[email protected]3130a8532008-09-15 18:37:11668 } tests[] = {
669 { // Check that #hash is removed.
670 "http://www.google.com:78/foobar?query=1#hash",
671 "http://www.google.com:78/foobar?query=1",
[email protected]3130a8532008-09-15 18:37:11672 },
673 { // The reference may itself contain # -- strip all of it.
674 "http://192.168.0.1?query=1#hash#10#11#13#14",
675 "http://192.168.0.1/?query=1",
[email protected]3130a8532008-09-15 18:37:11676 },
677 { // Strip username/password.
678 "http://user:[email protected]",
679 "http://google.com/",
[email protected]9b8da4a2013-11-29 19:59:30680 },
681 { // https scheme
682 "https://www.google.com:78/foobar?query=1#hash",
683 "https://www.google.com:78/foobar?query=1",
[email protected]9b8da4a2013-11-29 19:59:30684 },
685 { // WebSocket's ws scheme
686 "ws://www.google.com:78/foobar?query=1#hash",
687 "ws://www.google.com:78/foobar?query=1",
[email protected]9b8da4a2013-11-29 19:59:30688 },
689 { // WebSocket's wss scheme
690 "wss://www.google.com:78/foobar?query=1#hash",
691 "wss://www.google.com:78/foobar?query=1",
[email protected]3130a8532008-09-15 18:37:11692 }
693 };
viettrungluue4a8b882014-10-16 06:17:38694 for (size_t i = 0; i < arraysize(tests); ++i) {
nharper834c49b2015-06-03 23:46:43695 SCOPED_TRACE(i);
696
[email protected]3130a8532008-09-15 18:37:11697 GURL url(GURL(tests[i].url));
698 std::string expected_spec(tests[i].expected_spec);
[email protected]3130a8532008-09-15 18:37:11699
700 EXPECT_EQ(expected_spec, HttpUtil::SpecForRequest(url));
[email protected]3130a8532008-09-15 18:37:11701 }
702}
[email protected]fe3d9d772009-01-23 00:39:47703
[email protected]9b8da4a2013-11-29 19:59:30704// Test SpecForRequest() for "ftp" scheme.
705TEST(HttpUtilTest, SpecForRequestForUrlWithFtpScheme) {
706 GURL ftp_url("ftp://user:[email protected]/pub/chromium/");
707 EXPECT_EQ("ftp://google.com/pub/chromium/",
708 HttpUtil::SpecForRequest(ftp_url));
709}
710
[email protected]fe3d9d772009-01-23 00:39:47711TEST(HttpUtilTest, GenerateAcceptLanguageHeader) {
712 EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6"),
713 HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de"));
714 EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6,ko;q=0.4,zh-CN;q=0.2,"
715 "ja;q=0.2"),
716 HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de,ko,zh-CN,ja"));
717}
718
[email protected]b1fd7192012-01-31 01:00:49719// HttpResponseHeadersTest.GetMimeType also tests ParseContentType.
720TEST(HttpUtilTest, ParseContentType) {
721 const struct {
thestig9d3bb0c2015-01-24 00:49:51722 const char* const content_type;
723 const char* const expected_mime_type;
724 const char* const expected_charset;
[email protected]b1fd7192012-01-31 01:00:49725 const bool expected_had_charset;
thestig9d3bb0c2015-01-24 00:49:51726 const char* const expected_boundary;
[email protected]b1fd7192012-01-31 01:00:49727 } tests[] = {
728 { "text/html; charset=utf-8",
729 "text/html",
730 "utf-8",
731 true,
732 ""
733 },
734 { "text/html; charset =utf-8",
735 "text/html",
736 "utf-8",
737 true,
738 ""
739 },
740 { "text/html; charset= utf-8",
741 "text/html",
742 "utf-8",
743 true,
744 ""
745 },
746 { "text/html; charset=utf-8 ",
747 "text/html",
748 "utf-8",
749 true,
750 ""
751 },
752 { "text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs\"",
753 "text/html",
754 "",
755 false,
756 "\"WebKit-ada-df-dsf-adsfadsfs\""
757 },
758 { "text/html; boundary =\"WebKit-ada-df-dsf-adsfadsfs\"",
759 "text/html",
760 "",
761 false,
762 "\"WebKit-ada-df-dsf-adsfadsfs\""
763 },
764 { "text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\"",
765 "text/html",
766 "",
767 false,
768 "\"WebKit-ada-df-dsf-adsfadsfs\""
769 },
770 { "text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\" ",
771 "text/html",
772 "",
773 false,
774 "\"WebKit-ada-df-dsf-adsfadsfs\""
775 },
776 { "text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs \"",
777 "text/html",
778 "",
779 false,
780 "\"WebKit-ada-df-dsf-adsfadsfs \""
781 },
782 { "text/html; boundary=WebKit-ada-df-dsf-adsfadsfs",
783 "text/html",
784 "",
785 false,
786 "WebKit-ada-df-dsf-adsfadsfs"
787 },
788 // TODO(abarth): Add more interesting test cases.
789 };
viettrungluue4a8b882014-10-16 06:17:38790 for (size_t i = 0; i < arraysize(tests); ++i) {
[email protected]b1fd7192012-01-31 01:00:49791 std::string mime_type;
792 std::string charset;
793 bool had_charset = false;
794 std::string boundary;
ttuttle859dc7a2015-04-23 19:42:29795 HttpUtil::ParseContentType(tests[i].content_type, &mime_type, &charset,
796 &had_charset, &boundary);
[email protected]b1fd7192012-01-31 01:00:49797 EXPECT_EQ(tests[i].expected_mime_type, mime_type) << "i=" << i;
798 EXPECT_EQ(tests[i].expected_charset, charset) << "i=" << i;
799 EXPECT_EQ(tests[i].expected_had_charset, had_charset) << "i=" << i;
800 EXPECT_EQ(tests[i].expected_boundary, boundary) << "i=" << i;
801 }
802}
803
sclittle0a4f767d2016-12-03 03:45:54804TEST(HttpUtilTest, ParseContentRangeHeader) {
805 const struct {
806 const char* const content_range_header_spec;
807 bool expected_return_value;
808 int64_t expected_first_byte_position;
809 int64_t expected_last_byte_position;
810 int64_t expected_instance_length;
811 } tests[] = {
812 {"", false, -1, -1, -1},
813 {"megabytes 0-10/50", false, -1, -1, -1},
814 {"0-10/50", false, -1, -1, -1},
815 {"Bytes 0-50/51", true, 0, 50, 51},
816 {"bytes 0-50/51", true, 0, 50, 51},
817 {"bytes\t0-50/51", false, -1, -1, -1},
818 {" bytes 0-50/51", true, 0, 50, 51},
819 {" bytes 0 - 50 \t / \t51", true, 0, 50, 51},
820 {"bytes 0\t-\t50\t/\t51\t", true, 0, 50, 51},
821 {" \tbytes\t\t\t 0\t-\t50\t/\t51\t", true, 0, 50, 51},
sclittled43b2fb2016-12-17 03:20:47822 {"\t bytes \t 0 - 50 / 5 1", false, -1, -1, -1},
sclittle0a4f767d2016-12-03 03:45:54823 {"\t bytes \t 0 - 5 0 / 51", false, -1, -1, -1},
sclittled43b2fb2016-12-17 03:20:47824 {"bytes 50-0/51", false, -1, -1, -1},
sclittle0a4f767d2016-12-03 03:45:54825 {"bytes * /*", false, -1, -1, -1},
826 {"bytes * / * ", false, -1, -1, -1},
sclittled43b2fb2016-12-17 03:20:47827 {"bytes 0-50/*", false, -1, -1, -1},
828 {"bytes 0-50 / * ", false, -1, -1, -1},
sclittle0a4f767d2016-12-03 03:45:54829 {"bytes 0-10000000000/10000000001", true, 0, 10000000000ll,
830 10000000001ll},
sclittled43b2fb2016-12-17 03:20:47831 {"bytes 0-10000000000/10000000000", false, -1, -1, -1},
sclittle0a4f767d2016-12-03 03:45:54832 // 64 bit wraparound.
sclittled43b2fb2016-12-17 03:20:47833 {"bytes 0 - 9223372036854775807 / 100", false, -1, -1, -1},
sclittle0a4f767d2016-12-03 03:45:54834 // 64 bit wraparound.
sclittled43b2fb2016-12-17 03:20:47835 {"bytes 0 - 100 / -9223372036854775808", false, -1, -1, -1},
836 {"bytes */50", false, -1, -1, -1},
837 {"bytes 0-50/10", false, -1, -1, -1},
838 {"bytes 40-50/45", false, -1, -1, -1},
839 {"bytes 0-50/-10", false, -1, -1, -1},
sclittle0a4f767d2016-12-03 03:45:54840 {"bytes 0-0/1", true, 0, 0, 1},
841 {"bytes 0-40000000000000000000/40000000000000000001", false, -1, -1, -1},
842 {"bytes 1-/100", false, -1, -1, -1},
843 {"bytes -/100", false, -1, -1, -1},
844 {"bytes -1/100", false, -1, -1, -1},
sclittled43b2fb2016-12-17 03:20:47845 {"bytes 0-1233/*", false, -1, -1, -1},
sclittle0a4f767d2016-12-03 03:45:54846 {"bytes -123 - -1/100", false, -1, -1, -1},
847 };
848
849 for (const auto& test : tests) {
850 int64_t first_byte_position, last_byte_position, instance_length;
851 EXPECT_EQ(test.expected_return_value,
sclittled43b2fb2016-12-17 03:20:47852 HttpUtil::ParseContentRangeHeaderFor206(
sclittle0a4f767d2016-12-03 03:45:54853 test.content_range_header_spec, &first_byte_position,
854 &last_byte_position, &instance_length))
855 << test.content_range_header_spec;
856 EXPECT_EQ(test.expected_first_byte_position, first_byte_position)
857 << test.content_range_header_spec;
858 EXPECT_EQ(test.expected_last_byte_position, last_byte_position)
859 << test.content_range_header_spec;
860 EXPECT_EQ(test.expected_instance_length, instance_length)
861 << test.content_range_header_spec;
862 }
863}
864
ttuttle324834652014-11-06 22:38:47865TEST(HttpUtilTest, ParseRetryAfterHeader) {
maksim.sisoveebbdec2016-10-24 14:07:27866 base::Time::Exploded now_exploded = {2014, 11, 4, 5, 22, 39, 30, 0};
maksim.sisovc8c6cd12016-12-20 13:36:00867 base::Time now;
868 EXPECT_TRUE(base::Time::FromUTCExploded(now_exploded, &now));
ttuttle324834652014-11-06 22:38:47869
maksim.sisoveebbdec2016-10-24 14:07:27870 base::Time::Exploded later_exploded = {2015, 1, 5, 1, 12, 34, 56, 0};
maksim.sisovc8c6cd12016-12-20 13:36:00871 base::Time later;
872 EXPECT_TRUE(base::Time::FromUTCExploded(later_exploded, &later));
ttuttle324834652014-11-06 22:38:47873
874 const struct {
875 const char* retry_after_string;
876 bool expected_return_value;
877 base::TimeDelta expected_retry_after;
878 } tests[] = {
879 { "", false, base::TimeDelta() },
880 { "-3", false, base::TimeDelta() },
881 { "-2", false, base::TimeDelta() },
882 { "-1", false, base::TimeDelta() },
883 { "0", true, base::TimeDelta::FromSeconds(0) },
884 { "1", true, base::TimeDelta::FromSeconds(1) },
885 { "2", true, base::TimeDelta::FromSeconds(2) },
886 { "3", true, base::TimeDelta::FromSeconds(3) },
887 { "60", true, base::TimeDelta::FromSeconds(60) },
888 { "3600", true, base::TimeDelta::FromSeconds(3600) },
889 { "86400", true, base::TimeDelta::FromSeconds(86400) },
890 { "Thu, 1 Jan 2015 12:34:56 GMT", true, later - now },
891 { "Mon, 1 Jan 1900 12:34:56 GMT", false, base::TimeDelta() }
892 };
893
894 for (size_t i = 0; i < arraysize(tests); ++i) {
895 base::TimeDelta retry_after;
896 bool return_value = HttpUtil::ParseRetryAfterHeader(
897 tests[i].retry_after_string, now, &retry_after);
898 EXPECT_EQ(tests[i].expected_return_value, return_value)
899 << "Test case " << i << ": expected " << tests[i].expected_return_value
900 << " but got " << return_value << ".";
901 if (tests[i].expected_return_value && return_value) {
902 EXPECT_EQ(tests[i].expected_retry_after, retry_after)
903 << "Test case " << i << ": expected "
904 << tests[i].expected_retry_after.InSeconds() << "s but got "
905 << retry_after.InSeconds() << "s.";
906 }
907 }
908}
909
[email protected]e3fe59b2010-09-30 13:28:44910namespace {
[email protected]213b99a2010-10-22 16:04:49911void CheckCurrentNameValuePair(HttpUtil::NameValuePairsIterator* parser,
912 bool expect_valid,
913 std::string expected_name,
914 std::string expected_value) {
[email protected]e3fe59b2010-09-30 13:28:44915 ASSERT_EQ(expect_valid, parser->valid());
[email protected]213b99a2010-10-22 16:04:49916 if (!expect_valid) {
[email protected]e3fe59b2010-09-30 13:28:44917 return;
918 }
[email protected]213b99a2010-10-22 16:04:49919
920 // Let's make sure that these never change (i.e., when a quoted value is
921 // unquoted, it should be cached on the first calls and not regenerated
922 // later).
923 std::string::const_iterator first_value_begin = parser->value_begin();
924 std::string::const_iterator first_value_end = parser->value_end();
925
[email protected]e3fe59b2010-09-30 13:28:44926 ASSERT_EQ(expected_name, std::string(parser->name_begin(),
927 parser->name_end()));
928 ASSERT_EQ(expected_name, parser->name());
929 ASSERT_EQ(expected_value, std::string(parser->value_begin(),
930 parser->value_end()));
931 ASSERT_EQ(expected_value, parser->value());
[email protected]213b99a2010-10-22 16:04:49932
933 // Make sure they didn't/don't change.
934 ASSERT_TRUE(first_value_begin == parser->value_begin());
935 ASSERT_TRUE(first_value_end == parser->value_end());
936}
937
938void CheckNextNameValuePair(HttpUtil::NameValuePairsIterator* parser,
939 bool expect_next,
940 bool expect_valid,
941 std::string expected_name,
942 std::string expected_value) {
943 ASSERT_EQ(expect_next, parser->GetNext());
944 ASSERT_EQ(expect_valid, parser->valid());
945 if (!expect_next || !expect_valid) {
946 return;
947 }
948
949 CheckCurrentNameValuePair(parser,
950 expect_valid,
951 expected_name,
952 expected_value);
[email protected]e3fe59b2010-09-30 13:28:44953}
954
955void CheckInvalidNameValuePair(std::string valid_part,
956 std::string invalid_part) {
957 std::string whole_string = valid_part + invalid_part;
958
959 HttpUtil::NameValuePairsIterator valid_parser(valid_part.begin(),
960 valid_part.end(),
961 ';');
962 HttpUtil::NameValuePairsIterator invalid_parser(whole_string.begin(),
963 whole_string.end(),
964 ';');
965
966 ASSERT_TRUE(valid_parser.valid());
967 ASSERT_TRUE(invalid_parser.valid());
968
969 // Both parsers should return all the same values until "valid_parser" is
970 // exhausted.
971 while (valid_parser.GetNext()) {
972 ASSERT_TRUE(invalid_parser.GetNext());
973 ASSERT_TRUE(valid_parser.valid());
974 ASSERT_TRUE(invalid_parser.valid());
975 ASSERT_EQ(valid_parser.name(), invalid_parser.name());
976 ASSERT_EQ(valid_parser.value(), invalid_parser.value());
977 }
978
979 // valid_parser is exhausted and remains 'valid'
980 ASSERT_TRUE(valid_parser.valid());
981
982 // invalid_parser's corresponding call to GetNext also returns false...
983 ASSERT_FALSE(invalid_parser.GetNext());
984 // ...but the parser is in an invalid state.
985 ASSERT_FALSE(invalid_parser.valid());
986}
987
ttuttle859dc7a2015-04-23 19:42:29988} // namespace
[email protected]e3fe59b2010-09-30 13:28:44989
[email protected]213b99a2010-10-22 16:04:49990TEST(HttpUtilTest, NameValuePairsIteratorCopyAndAssign) {
991 std::string data = "alpha='\\'a\\''; beta=\" b \"; cappa='c;'; delta=\"d\"";
992 HttpUtil::NameValuePairsIterator parser_a(data.begin(), data.end(), ';');
993
994 EXPECT_TRUE(parser_a.valid());
995 ASSERT_NO_FATAL_FAILURE(
996 CheckNextNameValuePair(&parser_a, true, true, "alpha", "'a'"));
997
998 HttpUtil::NameValuePairsIterator parser_b(parser_a);
999 // a and b now point to same location
1000 ASSERT_NO_FATAL_FAILURE(
1001 CheckCurrentNameValuePair(&parser_b, true, "alpha", "'a'"));
1002 ASSERT_NO_FATAL_FAILURE(
1003 CheckCurrentNameValuePair(&parser_a, true, "alpha", "'a'"));
1004
1005 // advance a, no effect on b
1006 ASSERT_NO_FATAL_FAILURE(
1007 CheckNextNameValuePair(&parser_a, true, true, "beta", " b "));
1008 ASSERT_NO_FATAL_FAILURE(
1009 CheckCurrentNameValuePair(&parser_b, true, "alpha", "'a'"));
1010
1011 // assign b the current state of a, no effect on a
1012 parser_b = parser_a;
1013 ASSERT_NO_FATAL_FAILURE(
1014 CheckCurrentNameValuePair(&parser_b, true, "beta", " b "));
1015 ASSERT_NO_FATAL_FAILURE(
1016 CheckCurrentNameValuePair(&parser_a, true, "beta", " b "));
1017
1018 // advance b, no effect on a
1019 ASSERT_NO_FATAL_FAILURE(
1020 CheckNextNameValuePair(&parser_b, true, true, "cappa", "c;"));
1021 ASSERT_NO_FATAL_FAILURE(
1022 CheckCurrentNameValuePair(&parser_a, true, "beta", " b "));
1023}
1024
[email protected]e3fe59b2010-09-30 13:28:441025TEST(HttpUtilTest, NameValuePairsIteratorEmptyInput) {
[email protected]007b3f82013-04-09 08:46:451026 std::string data;
[email protected]e3fe59b2010-09-30 13:28:441027 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
1028
1029 EXPECT_TRUE(parser.valid());
[email protected]007b3f82013-04-09 08:46:451030 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
1031 &parser, false, true, std::string(), std::string()));
[email protected]e3fe59b2010-09-30 13:28:441032}
1033
1034TEST(HttpUtilTest, NameValuePairsIterator) {
[email protected]213b99a2010-10-22 16:04:491035 std::string data = "alpha=1; beta= 2 ;cappa =' 3; ';"
1036 "delta= \" \\\"4\\\" \"; e= \" '5'\"; e=6;"
1037 "f='\\'\\h\\e\\l\\l\\o\\ \\w\\o\\r\\l\\d\\'';"
1038 "g=''; h='hello'";
[email protected]e3fe59b2010-09-30 13:28:441039 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
1040 EXPECT_TRUE(parser.valid());
1041
1042 ASSERT_NO_FATAL_FAILURE(
[email protected]213b99a2010-10-22 16:04:491043 CheckNextNameValuePair(&parser, true, true, "alpha", "1"));
[email protected]e3fe59b2010-09-30 13:28:441044 ASSERT_NO_FATAL_FAILURE(
[email protected]213b99a2010-10-22 16:04:491045 CheckNextNameValuePair(&parser, true, true, "beta", "2"));
[email protected]e3fe59b2010-09-30 13:28:441046 ASSERT_NO_FATAL_FAILURE(
[email protected]213b99a2010-10-22 16:04:491047 CheckNextNameValuePair(&parser, true, true, "cappa", " 3; "));
[email protected]e3fe59b2010-09-30 13:28:441048 ASSERT_NO_FATAL_FAILURE(
[email protected]213b99a2010-10-22 16:04:491049 CheckNextNameValuePair(&parser, true, true, "delta", " \"4\" "));
[email protected]e3fe59b2010-09-30 13:28:441050 ASSERT_NO_FATAL_FAILURE(
[email protected]213b99a2010-10-22 16:04:491051 CheckNextNameValuePair(&parser, true, true, "e", " '5'"));
[email protected]e3fe59b2010-09-30 13:28:441052 ASSERT_NO_FATAL_FAILURE(
[email protected]213b99a2010-10-22 16:04:491053 CheckNextNameValuePair(&parser, true, true, "e", "6"));
[email protected]e3fe59b2010-09-30 13:28:441054 ASSERT_NO_FATAL_FAILURE(
[email protected]213b99a2010-10-22 16:04:491055 CheckNextNameValuePair(&parser, true, true, "f", "'hello world'"));
1056 ASSERT_NO_FATAL_FAILURE(
[email protected]007b3f82013-04-09 08:46:451057 CheckNextNameValuePair(&parser, true, true, "g", std::string()));
[email protected]213b99a2010-10-22 16:04:491058 ASSERT_NO_FATAL_FAILURE(
1059 CheckNextNameValuePair(&parser, true, true, "h", "hello"));
[email protected]007b3f82013-04-09 08:46:451060 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
1061 &parser, false, true, std::string(), std::string()));
[email protected]e3fe59b2010-09-30 13:28:441062}
1063
estark83487b62015-07-27 17:11:141064TEST(HttpUtilTest, NameValuePairsIteratorOptionalValues) {
1065 std::string data = "alpha=1; beta;cappa ; delta; e ; f=1";
1066 // Test that the default parser requires values.
1067 HttpUtil::NameValuePairsIterator default_parser(data.begin(), data.end(),
1068 ';');
1069 EXPECT_TRUE(default_parser.valid());
1070 ASSERT_NO_FATAL_FAILURE(
1071 CheckNextNameValuePair(&default_parser, true, true, "alpha", "1"));
1072 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&default_parser, false, false,
1073 std::string(), std::string()));
1074
1075 HttpUtil::NameValuePairsIterator values_required_parser(
1076 data.begin(), data.end(), ';',
mek9b28f422016-05-13 21:46:231077 HttpUtil::NameValuePairsIterator::Values::REQUIRED,
1078 HttpUtil::NameValuePairsIterator::Quotes::NOT_STRICT);
estark83487b62015-07-27 17:11:141079 EXPECT_TRUE(values_required_parser.valid());
1080 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&values_required_parser, true,
1081 true, "alpha", "1"));
1082 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
1083 &values_required_parser, false, false, std::string(), std::string()));
1084
1085 HttpUtil::NameValuePairsIterator parser(
1086 data.begin(), data.end(), ';',
mek9b28f422016-05-13 21:46:231087 HttpUtil::NameValuePairsIterator::Values::NOT_REQUIRED,
1088 HttpUtil::NameValuePairsIterator::Quotes::NOT_STRICT);
estark83487b62015-07-27 17:11:141089 EXPECT_TRUE(parser.valid());
1090
1091 ASSERT_NO_FATAL_FAILURE(
1092 CheckNextNameValuePair(&parser, true, true, "alpha", "1"));
1093 ASSERT_NO_FATAL_FAILURE(
1094 CheckNextNameValuePair(&parser, true, true, "beta", std::string()));
1095 ASSERT_NO_FATAL_FAILURE(
1096 CheckNextNameValuePair(&parser, true, true, "cappa", std::string()));
1097 ASSERT_NO_FATAL_FAILURE(
1098 CheckNextNameValuePair(&parser, true, true, "delta", std::string()));
1099 ASSERT_NO_FATAL_FAILURE(
1100 CheckNextNameValuePair(&parser, true, true, "e", std::string()));
1101 ASSERT_NO_FATAL_FAILURE(
1102 CheckNextNameValuePair(&parser, true, true, "f", "1"));
1103 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&parser, false, true,
1104 std::string(), std::string()));
1105 EXPECT_TRUE(parser.valid());
1106}
1107
[email protected]e3fe59b2010-09-30 13:28:441108TEST(HttpUtilTest, NameValuePairsIteratorIllegalInputs) {
1109 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; beta"));
[email protected]007b3f82013-04-09 08:46:451110 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "beta"));
[email protected]e3fe59b2010-09-30 13:28:441111
1112 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; 'beta'=2"));
[email protected]007b3f82013-04-09 08:46:451113 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "'beta'=2"));
[email protected]213b99a2010-10-22 16:04:491114 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";beta="));
1115 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1",
1116 ";beta=;cappa=2"));
[email protected]e3fe59b2010-09-30 13:28:441117
1118 // According to the spec this is an error, but it doesn't seem appropriate to
1119 // change our behaviour to be less permissive at this time.
1120 // See NameValuePairsIteratorExtraSeparators test
1121 // ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";; beta=2"));
1122}
1123
1124// If we are going to support extra separators against the spec, let's just make
1125// sure they work rationally.
1126TEST(HttpUtilTest, NameValuePairsIteratorExtraSeparators) {
1127 std::string data = " ; ;;alpha=1; ;; ; beta= 2;cappa=3;;; ; ";
1128 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
1129 EXPECT_TRUE(parser.valid());
1130
1131 ASSERT_NO_FATAL_FAILURE(
[email protected]213b99a2010-10-22 16:04:491132 CheckNextNameValuePair(&parser, true, true, "alpha", "1"));
[email protected]e3fe59b2010-09-30 13:28:441133 ASSERT_NO_FATAL_FAILURE(
[email protected]213b99a2010-10-22 16:04:491134 CheckNextNameValuePair(&parser, true, true, "beta", "2"));
[email protected]e3fe59b2010-09-30 13:28:441135 ASSERT_NO_FATAL_FAILURE(
[email protected]213b99a2010-10-22 16:04:491136 CheckNextNameValuePair(&parser, true, true, "cappa", "3"));
[email protected]007b3f82013-04-09 08:46:451137 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
1138 &parser, false, true, std::string(), std::string()));
[email protected]e3fe59b2010-09-30 13:28:441139}
1140
1141// See comments on the implementation of NameValuePairsIterator::GetNext
1142// regarding this derogation from the spec.
1143TEST(HttpUtilTest, NameValuePairsIteratorMissingEndQuote) {
1144 std::string data = "name='value";
1145 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
1146 EXPECT_TRUE(parser.valid());
1147
1148 ASSERT_NO_FATAL_FAILURE(
[email protected]213b99a2010-10-22 16:04:491149 CheckNextNameValuePair(&parser, true, true, "name", "value"));
[email protected]007b3f82013-04-09 08:46:451150 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
1151 &parser, false, true, std::string(), std::string()));
[email protected]e3fe59b2010-09-30 13:28:441152}
ttuttle859dc7a2015-04-23 19:42:291153
mek9b28f422016-05-13 21:46:231154TEST(HttpUtilTest, NameValuePairsIteratorStrictQuotesEscapedEndQuote) {
1155 std::string data = "foo=bar; name=\"value\\\"";
1156 HttpUtil::NameValuePairsIterator parser(
1157 data.begin(), data.end(), ';',
1158 HttpUtil::NameValuePairsIterator::Values::REQUIRED,
1159 HttpUtil::NameValuePairsIterator::Quotes::STRICT_QUOTES);
1160 EXPECT_TRUE(parser.valid());
1161
1162 ASSERT_NO_FATAL_FAILURE(
1163 CheckNextNameValuePair(&parser, true, true, "foo", "bar"));
1164 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&parser, false, false,
1165 std::string(), std::string()));
1166}
1167
1168TEST(HttpUtilTest, NameValuePairsIteratorStrictQuotesQuoteInValue) {
1169 std::string data = "foo=\"bar\"; name=\"va\"lue\"";
1170 HttpUtil::NameValuePairsIterator parser(
1171 data.begin(), data.end(), ';',
1172 HttpUtil::NameValuePairsIterator::Values::REQUIRED,
1173 HttpUtil::NameValuePairsIterator::Quotes::STRICT_QUOTES);
1174 EXPECT_TRUE(parser.valid());
1175
1176 ASSERT_NO_FATAL_FAILURE(
1177 CheckNextNameValuePair(&parser, true, true, "foo", "bar"));
1178 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&parser, false, false,
1179 std::string(), std::string()));
1180}
1181
1182TEST(HttpUtilTest, NameValuePairsIteratorStrictQuotesMissingEndQuote) {
1183 std::string data = "foo=\"bar\"; name=\"value";
1184 HttpUtil::NameValuePairsIterator parser(
1185 data.begin(), data.end(), ';',
1186 HttpUtil::NameValuePairsIterator::Values::REQUIRED,
1187 HttpUtil::NameValuePairsIterator::Quotes::STRICT_QUOTES);
1188 EXPECT_TRUE(parser.valid());
1189
1190 ASSERT_NO_FATAL_FAILURE(
1191 CheckNextNameValuePair(&parser, true, true, "foo", "bar"));
1192 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&parser, false, false,
1193 std::string(), std::string()));
1194}
1195
1196TEST(HttpUtilTest, NameValuePairsIteratorStrictQuotesSingleQuotes) {
1197 std::string data = "foo=\"bar\"; name='value; ok=it'";
1198 HttpUtil::NameValuePairsIterator parser(
1199 data.begin(), data.end(), ';',
1200 HttpUtil::NameValuePairsIterator::Values::REQUIRED,
1201 HttpUtil::NameValuePairsIterator::Quotes::STRICT_QUOTES);
1202 EXPECT_TRUE(parser.valid());
1203
1204 ASSERT_NO_FATAL_FAILURE(
1205 CheckNextNameValuePair(&parser, true, true, "foo", "bar"));
1206 ASSERT_NO_FATAL_FAILURE(
1207 CheckNextNameValuePair(&parser, true, true, "name", "'value"));
1208 ASSERT_NO_FATAL_FAILURE(
1209 CheckNextNameValuePair(&parser, true, true, "ok", "it'"));
1210}
1211
jamartin2edf0e7c2016-02-29 17:39:221212TEST(HttpUtilTest, HasValidators) {
1213 const char* const kMissing = "";
1214 const char* const kEtagEmpty = "\"\"";
1215 const char* const kEtagStrong = "\"strong\"";
1216 const char* const kEtagWeak = "W/\"weak\"";
1217 const char* const kLastModified = "Tue, 15 Nov 1994 12:45:26 GMT";
1218 const char* const kLastModifiedInvalid = "invalid";
1219
1220 const HttpVersion v0_9 = HttpVersion(0, 9);
1221 EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kMissing, kMissing));
1222 EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagStrong, kMissing));
1223 EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagWeak, kMissing));
1224 EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagEmpty, kMissing));
1225
1226 EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kMissing, kLastModified));
1227 EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagStrong, kLastModified));
1228 EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagWeak, kLastModified));
1229 EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagEmpty, kLastModified));
1230
1231 EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kMissing, kLastModifiedInvalid));
1232 EXPECT_FALSE(
1233 HttpUtil::HasValidators(v0_9, kEtagStrong, kLastModifiedInvalid));
1234 EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagWeak, kLastModifiedInvalid));
1235 EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagEmpty, kLastModifiedInvalid));
1236
1237 const HttpVersion v1_0 = HttpVersion(1, 0);
1238 EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kMissing, kMissing));
1239 EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagStrong, kMissing));
1240 EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagWeak, kMissing));
1241 EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagEmpty, kMissing));
1242
1243 EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kMissing, kLastModified));
1244 EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kEtagStrong, kLastModified));
1245 EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kEtagWeak, kLastModified));
1246 EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kEtagEmpty, kLastModified));
1247
1248 EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kMissing, kLastModifiedInvalid));
1249 EXPECT_FALSE(
1250 HttpUtil::HasValidators(v1_0, kEtagStrong, kLastModifiedInvalid));
1251 EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagWeak, kLastModifiedInvalid));
1252 EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagEmpty, kLastModifiedInvalid));
1253
1254 const HttpVersion v1_1 = HttpVersion(1, 1);
1255 EXPECT_FALSE(HttpUtil::HasValidators(v1_1, kMissing, kMissing));
1256 EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagStrong, kMissing));
1257 EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagWeak, kMissing));
1258 EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kMissing));
1259
1260 EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kMissing, kLastModified));
1261 EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagStrong, kLastModified));
1262 EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagWeak, kLastModified));
1263 EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kLastModified));
1264
1265 EXPECT_FALSE(HttpUtil::HasValidators(v1_1, kMissing, kLastModifiedInvalid));
1266 EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagStrong, kLastModifiedInvalid));
1267 EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagWeak, kLastModifiedInvalid));
1268 EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kLastModifiedInvalid));
1269}
1270
riceab0723322016-07-13 03:53:441271TEST(HttpUtilTest, IsValidHeaderValue) {
1272 const char* const invalid_values[] = {
1273 "X-Requested-With: chrome${NUL}Sec-Unsafe: injected",
1274 "X-Requested-With: chrome\r\nSec-Unsafe: injected",
1275 "X-Requested-With: chrome\nSec-Unsafe: injected",
1276 "X-Requested-With: chrome\rSec-Unsafe: injected",
1277 };
1278 for (const std::string& value : invalid_values) {
1279 std::string replaced = value;
1280 base::ReplaceSubstringsAfterOffset(&replaced, 0, "${NUL}",
1281 std::string(1, '\0'));
1282 EXPECT_FALSE(HttpUtil::IsValidHeaderValue(replaced)) << replaced;
1283 }
1284
1285 // Check that all characters permitted by RFC7230 3.2.6 are allowed.
1286 std::string allowed = "\t";
1287 for (char c = '\x20'; c < '\x7F'; ++c) {
1288 allowed.append(1, c);
1289 }
1290 for (int c = 0x80; c <= 0xFF; ++c) {
1291 allowed.append(1, static_cast<char>(c));
1292 }
1293 EXPECT_TRUE(HttpUtil::IsValidHeaderValue(allowed));
1294}
1295
ricea0753a6f42016-08-12 05:20:581296TEST(HttpUtilTest, IsToken) {
1297 EXPECT_TRUE(HttpUtil::IsToken("valid"));
tyoshino663b928c2016-09-06 11:59:121298 EXPECT_TRUE(HttpUtil::IsToken("!"));
1299 EXPECT_TRUE(HttpUtil::IsToken("~"));
1300
ricea0753a6f42016-08-12 05:20:581301 EXPECT_FALSE(HttpUtil::IsToken(""));
1302 EXPECT_FALSE(HttpUtil::IsToken(base::StringPiece()));
1303 EXPECT_FALSE(HttpUtil::IsToken("hello, world"));
tyoshino663b928c2016-09-06 11:59:121304 EXPECT_FALSE(HttpUtil::IsToken(" "));
1305 EXPECT_FALSE(HttpUtil::IsToken(base::StringPiece("\0", 1)));
1306 EXPECT_FALSE(HttpUtil::IsToken("\x01"));
ricea19b4014c2016-09-01 11:36:021307 EXPECT_FALSE(HttpUtil::IsToken("\x7F"));
tyoshino663b928c2016-09-06 11:59:121308 EXPECT_FALSE(HttpUtil::IsToken("\x80"));
1309 EXPECT_FALSE(HttpUtil::IsToken("\xff"));
ricea0753a6f42016-08-12 05:20:581310}
1311
eromanacf834a52016-12-06 21:13:271312TEST(HttpUtilTest, IsLWS) {
1313 EXPECT_FALSE(HttpUtil::IsLWS('\v'));
1314 EXPECT_FALSE(HttpUtil::IsLWS('\0'));
1315 EXPECT_FALSE(HttpUtil::IsLWS('1'));
1316 EXPECT_FALSE(HttpUtil::IsLWS('a'));
1317 EXPECT_FALSE(HttpUtil::IsLWS('.'));
1318 EXPECT_FALSE(HttpUtil::IsLWS('\n'));
1319 EXPECT_FALSE(HttpUtil::IsLWS('\r'));
1320
1321 EXPECT_TRUE(HttpUtil::IsLWS('\t'));
1322 EXPECT_TRUE(HttpUtil::IsLWS(' '));
1323}
1324
eustasc7d27da2017-04-06 10:33:201325TEST(HttpUtilTest, ParseAcceptEncoding) {
1326 const struct {
1327 const char* const value;
1328 const char* const expected;
1329 } tests[] = {
1330 {"", "*"},
1331 {"identity;q=1, *;q=0", "identity"},
1332 {"identity", "identity"},
1333 {"FOO, Bar", "bar|foo|identity"},
1334 {"foo; q=1", "foo|identity"},
1335 {"abc, foo; Q=1.0", "abc|foo|identity"},
1336 {"abc, foo;q= 1.00 , bar", "abc|bar|foo|identity"},
1337 {"abc, foo; q=1.000, bar", "abc|bar|foo|identity"},
1338 {"abc, foo ; q = 0 , bar", "abc|bar|identity"},
1339 {"abc, foo; q=0.0, bar", "abc|bar|identity"},
1340 {"abc, foo; q=0.00, bar", "abc|bar|identity"},
1341 {"abc, foo; q=0.000, bar", "abc|bar|identity"},
1342 {"abc, foo; q=0.001, bar", "abc|bar|foo|identity"},
1343 {"gzip", "gzip|identity|x-gzip"},
1344 {"x-gzip", "gzip|identity|x-gzip"},
1345 {"compress", "compress|identity|x-compress"},
1346 {"x-compress", "compress|identity|x-compress"},
1347 {"x-compress", "compress|identity|x-compress"},
1348 {"foo bar", "INVALID"},
1349 {"foo;", "INVALID"},
1350 {"foo;w=1", "INVALID"},
1351 {"foo;q+1", "INVALID"},
1352 {"foo;q=2", "INVALID"},
1353 {"foo;q=1.001", "INVALID"},
1354 {"foo;q=0.", "INVALID"},
1355 {"foo,\"bar\"", "INVALID"},
1356 };
1357
1358 for (size_t i = 0; i < arraysize(tests); ++i) {
1359 std::string value(tests[i].value);
1360 std::string reformatted;
1361 std::set<std::string> allowed_encodings;
1362 if (!HttpUtil::ParseAcceptEncoding(value, &allowed_encodings)) {
1363 reformatted = "INVALID";
1364 } else {
1365 std::vector<std::string> encodings_list;
1366 for (auto const& encoding : allowed_encodings)
1367 encodings_list.push_back(encoding);
1368 reformatted = base::JoinString(encodings_list, "|");
1369 }
1370 EXPECT_STREQ(tests[i].expected, reformatted.c_str())
1371 << "value=\"" << value << "\"";
1372 }
1373}
1374
1375TEST(HttpUtilTest, ParseContentEncoding) {
1376 const struct {
1377 const char* const value;
1378 const char* const expected;
1379 } tests[] = {
1380 {"", ""},
1381 {"identity;q=1, *;q=0", "INVALID"},
1382 {"identity", "identity"},
1383 {"FOO, zergli , Bar", "bar|foo|zergli"},
1384 {"foo, *", "INVALID"},
1385 {"foo,\"bar\"", "INVALID"},
1386 };
1387
1388 for (size_t i = 0; i < arraysize(tests); ++i) {
1389 std::string value(tests[i].value);
1390 std::string reformatted;
1391 std::set<std::string> used_encodings;
1392 if (!HttpUtil::ParseContentEncoding(value, &used_encodings)) {
1393 reformatted = "INVALID";
1394 } else {
1395 std::vector<std::string> encodings_list;
1396 for (auto const& encoding : used_encodings)
1397 encodings_list.push_back(encoding);
1398 reformatted = base::JoinString(encodings_list, "|");
1399 }
1400 EXPECT_STREQ(tests[i].expected, reformatted.c_str())
1401 << "value=\"" << value << "\"";
1402 }
1403}
1404
ttuttle859dc7a2015-04-23 19:42:291405} // namespace net