| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <algorithm> | 5 #include <algorithm> |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
| 9 #include "net/http/http_util.h" | 9 #include "net/http/http_util.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
| 11 | 11 |
| 12 using net::HttpUtil; | 12 using net::HttpUtil; |
| 13 | 13 |
| 14 namespace { | 14 namespace { |
| 15 class HttpUtilTest : public testing::Test {}; | 15 class HttpUtilTest : public testing::Test {}; |
| 16 } | 16 } |
| 17 | 17 |
| 18 TEST(HttpUtilTest, IsSafeHeader) { | 18 TEST(HttpUtilTest, IsSafeHeader) { |
| 19 static const char* unsafe_headers[] = { | 19 static const char* unsafe_headers[] = { |
| 20 "sec-", | 20 "sec-", "sEc-", |
| 21 "sEc-", | 21 "sec-foo", "sEc-FoO", |
| 22 "sec-foo", | 22 "proxy-", "pRoXy-", |
| 23 "sEc-FoO", | 23 "proxy-foo", "pRoXy-FoO", |
| 24 "proxy-", | 24 "accept-charset", "accept-encoding", |
| 25 "pRoXy-", | 25 "access-control-request-headers", "access-control-request-method", |
| 26 "proxy-foo", | 26 "connection", "content-length", |
| 27 "pRoXy-FoO", | 27 "cookie", "cookie2", |
| 28 "accept-charset", | 28 "content-transfer-encoding", "date", |
| 29 "accept-encoding", | 29 "expect", "host", |
| 30 "access-control-request-headers", | 30 "keep-alive", "origin", |
| 31 "access-control-request-method", | 31 "referer", "te", |
| 32 "connection", | 32 "trailer", "transfer-encoding", |
| 33 "content-length", | 33 "upgrade", "user-agent", |
| 34 "cookie", | 34 "via", |
| 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 }; | 35 }; |
| 50 for (size_t i = 0; i < arraysize(unsafe_headers); ++i) { | 36 for (size_t i = 0; i < arraysize(unsafe_headers); ++i) { |
| 51 EXPECT_FALSE(HttpUtil::IsSafeHeader(unsafe_headers[i])) | 37 EXPECT_FALSE(HttpUtil::IsSafeHeader(unsafe_headers[i])) |
| 52 << unsafe_headers[i]; | 38 << unsafe_headers[i]; |
| 53 EXPECT_FALSE(HttpUtil::IsSafeHeader(StringToUpperASCII(std::string( | 39 EXPECT_FALSE(HttpUtil::IsSafeHeader( |
| 54 unsafe_headers[i])))) << unsafe_headers[i]; | 40 StringToUpperASCII(std::string(unsafe_headers[i])))) |
| 41 << unsafe_headers[i]; |
| 55 } | 42 } |
| 56 static const char* safe_headers[] = { | 43 static const char* safe_headers[] = { |
| 57 "foo", | 44 "foo", "x-", |
| 58 "x-", | 45 "x-foo", "content-disposition", |
| 59 "x-foo", | 46 "update", "accept-charseta", |
| 60 "content-disposition", | 47 "accept_charset", "accept-encodinga", |
| 61 "update", | 48 "accept_encoding", "access-control-request-headersa", |
| 62 "accept-charseta", | 49 "access-control-request-header", "access_control_request_header", |
| 63 "accept_charset", | 50 "access-control-request-methoda", "access_control_request_method", |
| 64 "accept-encodinga", | 51 "connectiona", "content-lengtha", |
| 65 "accept_encoding", | 52 "content_length", "cookiea", |
| 66 "access-control-request-headersa", | 53 "cookie2a", "cookie3", |
| 67 "access-control-request-header", | 54 "content-transfer-encodinga", "content_transfer_encoding", |
| 68 "access_control_request_header", | 55 "datea", "expecta", |
| 69 "access-control-request-methoda", | 56 "hosta", "keep-alivea", |
| 70 "access_control_request_method", | 57 "keep_alive", "origina", |
| 71 "connectiona", | 58 "referera", "referrer", |
| 72 "content-lengtha", | 59 "tea", "trailera", |
| 73 "content_length", | 60 "transfer-encodinga", "transfer_encoding", |
| 74 "cookiea", | 61 "upgradea", "user-agenta", |
| 75 "cookie2a", | 62 "user_agent", "viaa", |
| 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 }; | 63 }; |
| 96 for (size_t i = 0; i < arraysize(safe_headers); ++i) { | 64 for (size_t i = 0; i < arraysize(safe_headers); ++i) { |
| 97 EXPECT_TRUE(HttpUtil::IsSafeHeader(safe_headers[i])) << safe_headers[i]; | 65 EXPECT_TRUE(HttpUtil::IsSafeHeader(safe_headers[i])) << safe_headers[i]; |
| 98 EXPECT_TRUE(HttpUtil::IsSafeHeader(StringToUpperASCII(std::string( | 66 EXPECT_TRUE(HttpUtil::IsSafeHeader( |
| 99 safe_headers[i])))) << safe_headers[i]; | 67 StringToUpperASCII(std::string(safe_headers[i])))) |
| 68 << safe_headers[i]; |
| 100 } | 69 } |
| 101 } | 70 } |
| 102 | 71 |
| 103 TEST(HttpUtilTest, HasHeader) { | 72 TEST(HttpUtilTest, HasHeader) { |
| 104 static const struct { | 73 static const struct { |
| 105 const char* headers; | 74 const char* headers; |
| 106 const char* name; | 75 const char* name; |
| 107 bool expected_result; | 76 bool expected_result; |
| 108 } tests[] = { | 77 } tests[] = { |
| 109 { "", "foo", false }, | 78 {"", "foo", false}, |
| 110 { "foo\r\nbar", "foo", false }, | 79 {"foo\r\nbar", "foo", false}, |
| 111 { "ffoo: 1", "foo", false }, | 80 {"ffoo: 1", "foo", false}, |
| 112 { "foo: 1", "foo", true }, | 81 {"foo: 1", "foo", true}, |
| 113 { "foo: 1\r\nbar: 2", "foo", true }, | 82 {"foo: 1\r\nbar: 2", "foo", true}, |
| 114 { "fOO: 1\r\nbar: 2", "foo", true }, | 83 {"fOO: 1\r\nbar: 2", "foo", true}, |
| 115 { "g: 0\r\nfoo: 1\r\nbar: 2", "foo", true }, | 84 {"g: 0\r\nfoo: 1\r\nbar: 2", "foo", true}, |
| 116 }; | 85 }; |
| 117 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 86 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
| 118 bool result = HttpUtil::HasHeader(tests[i].headers, tests[i].name); | 87 bool result = HttpUtil::HasHeader(tests[i].headers, tests[i].name); |
| 119 EXPECT_EQ(tests[i].expected_result, result); | 88 EXPECT_EQ(tests[i].expected_result, result); |
| 120 } | 89 } |
| 121 } | 90 } |
| 122 | 91 |
| 123 TEST(HttpUtilTest, StripHeaders) { | 92 TEST(HttpUtilTest, StripHeaders) { |
| 124 static const char* headers = | 93 static const char* headers = |
| 125 "Origin: origin\r\n" | 94 "Origin: origin\r\n" |
| 126 "Content-Type: text/plain\r\n" | 95 "Content-Type: text/plain\r\n" |
| 127 "Cookies: foo1\r\n" | 96 "Cookies: foo1\r\n" |
| 128 "Custom: baz\r\n" | 97 "Custom: baz\r\n" |
| 129 "COOKIES: foo2\r\n" | 98 "COOKIES: foo2\r\n" |
| 130 "Server: Apache\r\n" | 99 "Server: Apache\r\n" |
| 131 "OrIGin: origin2\r\n"; | 100 "OrIGin: origin2\r\n"; |
| 132 | 101 |
| 133 static const char* header_names[] = { | 102 static const char* header_names[] = {"origin", "content-type", "cookies"}; |
| 134 "origin", "content-type", "cookies" | |
| 135 }; | |
| 136 | 103 |
| 137 static const char* expected_stripped_headers = | 104 static const char* expected_stripped_headers = |
| 138 "Custom: baz\r\n" | 105 "Custom: baz\r\n" |
| 139 "Server: Apache\r\n"; | 106 "Server: Apache\r\n"; |
| 140 | 107 |
| 141 EXPECT_EQ(expected_stripped_headers, | 108 EXPECT_EQ( |
| 142 HttpUtil::StripHeaders(headers, header_names, | 109 expected_stripped_headers, |
| 143 arraysize(header_names))); | 110 HttpUtil::StripHeaders(headers, header_names, arraysize(header_names))); |
| 144 } | 111 } |
| 145 | 112 |
| 146 TEST(HttpUtilTest, HeadersIterator) { | 113 TEST(HttpUtilTest, HeadersIterator) { |
| 147 std::string headers = "foo: 1\t\r\nbar: hello world\r\nbaz: 3 \r\n"; | 114 std::string headers = "foo: 1\t\r\nbar: hello world\r\nbaz: 3 \r\n"; |
| 148 | 115 |
| 149 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); | 116 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); |
| 150 | 117 |
| 151 ASSERT_TRUE(it.GetNext()); | 118 ASSERT_TRUE(it.GetNext()); |
| 152 EXPECT_EQ(std::string("foo"), it.name()); | 119 EXPECT_EQ(std::string("foo"), it.name()); |
| 153 EXPECT_EQ(std::string("1"), it.values()); | 120 EXPECT_EQ(std::string("1"), it.values()); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 | 225 |
| 259 // Replace <backslash> X with X | 226 // Replace <backslash> X with X |
| 260 EXPECT_STREQ("\"xyzXabc\"", HttpUtil::Quote("xyzXabc").c_str()); | 227 EXPECT_STREQ("\"xyzXabc\"", HttpUtil::Quote("xyzXabc").c_str()); |
| 261 } | 228 } |
| 262 | 229 |
| 263 TEST(HttpUtilTest, LocateEndOfHeaders) { | 230 TEST(HttpUtilTest, LocateEndOfHeaders) { |
| 264 struct { | 231 struct { |
| 265 const char* input; | 232 const char* input; |
| 266 int expected_result; | 233 int expected_result; |
| 267 } tests[] = { | 234 } tests[] = { |
| 268 { "foo\r\nbar\r\n\r\n", 12 }, | 235 {"foo\r\nbar\r\n\r\n", 12}, |
| 269 { "foo\nbar\n\n", 9 }, | 236 {"foo\nbar\n\n", 9}, |
| 270 { "foo\r\nbar\r\n\r\njunk", 12 }, | 237 {"foo\r\nbar\r\n\r\njunk", 12}, |
| 271 { "foo\nbar\n\njunk", 9 }, | 238 {"foo\nbar\n\njunk", 9}, |
| 272 { "foo\nbar\n\r\njunk", 10 }, | 239 {"foo\nbar\n\r\njunk", 10}, |
| 273 { "foo\nbar\r\n\njunk", 10 }, | 240 {"foo\nbar\r\n\njunk", 10}, |
| 274 }; | 241 }; |
| 275 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 242 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
| 276 int input_len = static_cast<int>(strlen(tests[i].input)); | 243 int input_len = static_cast<int>(strlen(tests[i].input)); |
| 277 int eoh = HttpUtil::LocateEndOfHeaders(tests[i].input, input_len); | 244 int eoh = HttpUtil::LocateEndOfHeaders(tests[i].input, input_len); |
| 278 EXPECT_EQ(tests[i].expected_result, eoh); | 245 EXPECT_EQ(tests[i].expected_result, eoh); |
| 279 } | 246 } |
| 280 } | 247 } |
| 281 | 248 |
| 282 TEST(HttpUtilTest, AssembleRawHeaders) { | 249 TEST(HttpUtilTest, AssembleRawHeaders) { |
| 283 struct { | 250 struct { |
| 284 const char* input; // with '|' representing '\0' | 251 const char* input; // with '|' representing '\0' |
| 285 const char* expected_result; // with '\0' changed to '|' | 252 const char* expected_result; // with '\0' changed to '|' |
| 286 } tests[] = { | 253 } tests[] = { |
| 287 { "HTTP/1.0 200 OK\r\nFoo: 1\r\nBar: 2\r\n\r\n", | 254 {"HTTP/1.0 200 OK\r\nFoo: 1\r\nBar: 2\r\n\r\n", |
| 288 "HTTP/1.0 200 OK|Foo: 1|Bar: 2||" }, | 255 "HTTP/1.0 200 OK|Foo: 1|Bar: 2||"}, |
| 289 | 256 {"HTTP/1.0 200 OK\nFoo: 1\nBar: 2\n\n", |
| 290 { "HTTP/1.0 200 OK\nFoo: 1\nBar: 2\n\n", | 257 "HTTP/1.0 200 OK|Foo: 1|Bar: 2||"}, |
| 291 "HTTP/1.0 200 OK|Foo: 1|Bar: 2||" }, | 258 |
| 292 | 259 // Valid line continuation (single SP). |
| 293 // Valid line continuation (single SP). | 260 {"HTTP/1.0 200 OK\n" |
| 294 { | 261 "Foo: 1\n" |
| 295 "HTTP/1.0 200 OK\n" | 262 " continuation\n" |
| 296 "Foo: 1\n" | 263 "Bar: 2\n\n", |
| 297 " continuation\n" | 264 "HTTP/1.0 200 OK|" |
| 298 "Bar: 2\n\n", | 265 "Foo: 1 continuation|" |
| 299 | 266 "Bar: 2||"}, |
| 300 "HTTP/1.0 200 OK|" | 267 |
| 301 "Foo: 1 continuation|" | 268 // Valid line continuation (single HT). |
| 302 "Bar: 2||" | 269 {"HTTP/1.0 200 OK\n" |
| 303 }, | 270 "Foo: 1\n" |
| 304 | 271 "\tcontinuation\n" |
| 305 // Valid line continuation (single HT). | 272 "Bar: 2\n\n", |
| 306 { | 273 "HTTP/1.0 200 OK|" |
| 307 "HTTP/1.0 200 OK\n" | 274 "Foo: 1 continuation|" |
| 308 "Foo: 1\n" | 275 "Bar: 2||"}, |
| 309 "\tcontinuation\n" | 276 |
| 310 "Bar: 2\n\n", | 277 // Valid line continuation (multiple SP). |
| 311 | 278 {"HTTP/1.0 200 OK\n" |
| 312 "HTTP/1.0 200 OK|" | 279 "Foo: 1\n" |
| 313 "Foo: 1 continuation|" | 280 " continuation\n" |
| 314 "Bar: 2||" | 281 "Bar: 2\n\n", |
| 315 }, | 282 "HTTP/1.0 200 OK|" |
| 316 | 283 "Foo: 1 continuation|" |
| 317 // Valid line continuation (multiple SP). | 284 "Bar: 2||"}, |
| 318 { | 285 |
| 319 "HTTP/1.0 200 OK\n" | 286 // Valid line continuation (multiple HT). |
| 320 "Foo: 1\n" | 287 {"HTTP/1.0 200 OK\n" |
| 321 " continuation\n" | 288 "Foo: 1\n" |
| 322 "Bar: 2\n\n", | 289 "\t\t\tcontinuation\n" |
| 323 | 290 "Bar: 2\n\n", |
| 324 "HTTP/1.0 200 OK|" | 291 "HTTP/1.0 200 OK|" |
| 325 "Foo: 1 continuation|" | 292 "Foo: 1 continuation|" |
| 326 "Bar: 2||" | 293 "Bar: 2||"}, |
| 327 }, | 294 |
| 328 | 295 // Valid line continuation (mixed HT, SP). |
| 329 // Valid line continuation (multiple HT). | 296 {"HTTP/1.0 200 OK\n" |
| 330 { | 297 "Foo: 1\n" |
| 331 "HTTP/1.0 200 OK\n" | 298 " \t \t continuation\n" |
| 332 "Foo: 1\n" | 299 "Bar: 2\n\n", |
| 333 "\t\t\tcontinuation\n" | 300 "HTTP/1.0 200 OK|" |
| 334 "Bar: 2\n\n", | 301 "Foo: 1 continuation|" |
| 335 | 302 "Bar: 2||"}, |
| 336 "HTTP/1.0 200 OK|" | 303 |
| 337 "Foo: 1 continuation|" | 304 // Valid multi-line continuation |
| 338 "Bar: 2||" | 305 {"HTTP/1.0 200 OK\n" |
| 339 }, | 306 "Foo: 1\n" |
| 340 | 307 " continuation1\n" |
| 341 // Valid line continuation (mixed HT, SP). | 308 "\tcontinuation2\n" |
| 342 { | 309 " continuation3\n" |
| 343 "HTTP/1.0 200 OK\n" | 310 "Bar: 2\n\n", |
| 344 "Foo: 1\n" | 311 "HTTP/1.0 200 OK|" |
| 345 " \t \t continuation\n" | 312 "Foo: 1 continuation1 continuation2 continuation3|" |
| 346 "Bar: 2\n\n", | 313 "Bar: 2||"}, |
| 347 | 314 |
| 348 "HTTP/1.0 200 OK|" | 315 // Continuation of quoted value. |
| 349 "Foo: 1 continuation|" | 316 // This is different from what Firefox does, since it |
| 350 "Bar: 2||" | 317 // will preserve the LWS. |
| 351 }, | 318 {"HTTP/1.0 200 OK\n" |
| 352 | 319 "Etag: \"34534-d3\n" |
| 353 // Valid multi-line continuation | 320 " 134q\"\n" |
| 354 { | 321 "Bar: 2\n\n", |
| 355 "HTTP/1.0 200 OK\n" | 322 "HTTP/1.0 200 OK|" |
| 356 "Foo: 1\n" | 323 "Etag: \"34534-d3 134q\"|" |
| 357 " continuation1\n" | 324 "Bar: 2||"}, |
| 358 "\tcontinuation2\n" | 325 |
| 359 " continuation3\n" | 326 // Valid multi-line continuation, full LWS lines |
| 360 "Bar: 2\n\n", | 327 {"HTTP/1.0 200 OK\n" |
| 361 | 328 "Foo: 1\n" |
| 362 "HTTP/1.0 200 OK|" | 329 " \n" |
| 363 "Foo: 1 continuation1 continuation2 continuation3|" | 330 "\t\t\t\t\n" |
| 364 "Bar: 2||" | 331 "\t continuation\n" |
| 365 }, | 332 "Bar: 2\n\n", |
| 366 | 333 |
| 367 // Continuation of quoted value. | 334 // One SP per continued line = 3. |
| 368 // This is different from what Firefox does, since it | 335 "HTTP/1.0 200 OK|" |
| 369 // will preserve the LWS. | 336 "Foo: 1 continuation|" |
| 370 { | 337 "Bar: 2||"}, |
| 371 "HTTP/1.0 200 OK\n" | 338 |
| 372 "Etag: \"34534-d3\n" | 339 // Valid multi-line continuation, all LWS |
| 373 " 134q\"\n" | 340 {"HTTP/1.0 200 OK\n" |
| 374 "Bar: 2\n\n", | 341 "Foo: 1\n" |
| 375 | 342 " \n" |
| 376 "HTTP/1.0 200 OK|" | 343 "\t\t\t\t\n" |
| 377 "Etag: \"34534-d3 134q\"|" | 344 "\t \n" |
| 378 "Bar: 2||" | 345 "Bar: 2\n\n", |
| 379 }, | 346 |
| 380 | 347 // One SP per continued line = 3. |
| 381 // Valid multi-line continuation, full LWS lines | 348 "HTTP/1.0 200 OK|" |
| 382 { | 349 "Foo: 1 |" |
| 383 "HTTP/1.0 200 OK\n" | 350 "Bar: 2||"}, |
| 384 "Foo: 1\n" | 351 |
| 385 " \n" | 352 // Valid line continuation (No value bytes in first line). |
| 386 "\t\t\t\t\n" | 353 {"HTTP/1.0 200 OK\n" |
| 387 "\t continuation\n" | 354 "Foo:\n" |
| 388 "Bar: 2\n\n", | 355 " value\n" |
| 389 | 356 "Bar: 2\n\n", |
| 390 // One SP per continued line = 3. | 357 "HTTP/1.0 200 OK|" |
| 391 "HTTP/1.0 200 OK|" | 358 "Foo: value|" |
| 392 "Foo: 1 continuation|" | 359 "Bar: 2||"}, |
| 393 "Bar: 2||" | 360 |
| 394 }, | 361 // Not a line continuation (can't continue status line). |
| 395 | 362 {"HTTP/1.0 200 OK\n" |
| 396 // Valid multi-line continuation, all LWS | 363 " Foo: 1\n" |
| 397 { | 364 "Bar: 2\n\n", |
| 398 "HTTP/1.0 200 OK\n" | 365 "HTTP/1.0 200 OK|" |
| 399 "Foo: 1\n" | 366 " Foo: 1|" |
| 400 " \n" | 367 "Bar: 2||"}, |
| 401 "\t\t\t\t\n" | 368 |
| 402 "\t \n" | 369 // Not a line continuation (can't continue status line). |
| 403 "Bar: 2\n\n", | 370 {"HTTP/1.0\n" |
| 404 | 371 " 200 OK\n" |
| 405 // One SP per continued line = 3. | 372 "Foo: 1\n" |
| 406 "HTTP/1.0 200 OK|" | 373 "Bar: 2\n\n", |
| 407 "Foo: 1 |" | 374 "HTTP/1.0|" |
| 408 "Bar: 2||" | 375 " 200 OK|" |
| 409 }, | 376 "Foo: 1|" |
| 410 | 377 "Bar: 2||"}, |
| 411 // Valid line continuation (No value bytes in first line). | 378 |
| 412 { | 379 // Not a line continuation (can't continue status line). |
| 413 "HTTP/1.0 200 OK\n" | 380 {"HTTP/1.0 404\n" |
| 414 "Foo:\n" | 381 " Not Found\n" |
| 415 " value\n" | 382 "Foo: 1\n" |
| 416 "Bar: 2\n\n", | 383 "Bar: 2\n\n", |
| 417 | 384 "HTTP/1.0 404|" |
| 418 "HTTP/1.0 200 OK|" | 385 " Not Found|" |
| 419 "Foo: value|" | 386 "Foo: 1|" |
| 420 "Bar: 2||" | 387 "Bar: 2||"}, |
| 421 }, | 388 |
| 422 | 389 // Unterminated status line. |
| 423 // Not a line continuation (can't continue status line). | 390 {"HTTP/1.0 200 OK", "HTTP/1.0 200 OK||"}, |
| 424 { | 391 |
| 425 "HTTP/1.0 200 OK\n" | 392 // Single terminated, with headers |
| 426 " Foo: 1\n" | 393 {"HTTP/1.0 200 OK\n" |
| 427 "Bar: 2\n\n", | 394 "Foo: 1\n" |
| 428 | 395 "Bar: 2\n", |
| 429 "HTTP/1.0 200 OK|" | 396 "HTTP/1.0 200 OK|" |
| 430 " Foo: 1|" | 397 "Foo: 1|" |
| 431 "Bar: 2||" | 398 "Bar: 2||"}, |
| 432 }, | 399 |
| 433 | 400 // Not terminated, with headers |
| 434 // Not a line continuation (can't continue status line). | 401 {"HTTP/1.0 200 OK\n" |
| 435 { | 402 "Foo: 1\n" |
| 436 "HTTP/1.0\n" | 403 "Bar: 2", |
| 437 " 200 OK\n" | 404 "HTTP/1.0 200 OK|" |
| 438 "Foo: 1\n" | 405 "Foo: 1|" |
| 439 "Bar: 2\n\n", | 406 "Bar: 2||"}, |
| 440 | 407 |
| 441 "HTTP/1.0|" | 408 // Not a line continuation (VT) |
| 442 " 200 OK|" | 409 {"HTTP/1.0 200 OK\n" |
| 443 "Foo: 1|" | 410 "Foo: 1\n" |
| 444 "Bar: 2||" | 411 "\vInvalidContinuation\n" |
| 445 }, | 412 "Bar: 2\n\n", |
| 446 | 413 "HTTP/1.0 200 OK|" |
| 447 // Not a line continuation (can't continue status line). | 414 "Foo: 1|" |
| 448 { | 415 "\vInvalidContinuation|" |
| 449 "HTTP/1.0 404\n" | 416 "Bar: 2||"}, |
| 450 " Not Found\n" | 417 |
| 451 "Foo: 1\n" | 418 // Not a line continuation (formfeed) |
| 452 "Bar: 2\n\n", | 419 {"HTTP/1.0 200 OK\n" |
| 453 | 420 "Foo: 1\n" |
| 454 "HTTP/1.0 404|" | 421 "\fInvalidContinuation\n" |
| 455 " Not Found|" | 422 "Bar: 2\n\n", |
| 456 "Foo: 1|" | 423 "HTTP/1.0 200 OK|" |
| 457 "Bar: 2||" | 424 "Foo: 1|" |
| 458 }, | 425 "\fInvalidContinuation|" |
| 459 | 426 "Bar: 2||"}, |
| 460 // Unterminated status line. | 427 |
| 461 { | 428 // Not a line continuation -- can't continue header names. |
| 462 "HTTP/1.0 200 OK", | 429 {"HTTP/1.0 200 OK\n" |
| 463 | 430 "Serv\n" |
| 464 "HTTP/1.0 200 OK||" | 431 " er: Apache\n" |
| 465 }, | 432 "\tInvalidContinuation\n" |
| 466 | 433 "Bar: 2\n\n", |
| 467 // Single terminated, with headers | 434 "HTTP/1.0 200 OK|" |
| 468 { | 435 "Serv|" |
| 469 "HTTP/1.0 200 OK\n" | 436 " er: Apache|" |
| 470 "Foo: 1\n" | 437 "\tInvalidContinuation|" |
| 471 "Bar: 2\n", | 438 "Bar: 2||"}, |
| 472 | 439 |
| 473 "HTTP/1.0 200 OK|" | 440 // Not a line continuation -- no value to continue. |
| 474 "Foo: 1|" | 441 { |
| 475 "Bar: 2||" | 442 "HTTP/1.0 200 OK\n" |
| 476 }, | 443 "Foo: 1\n" |
| 477 | 444 "garbage\n" |
| 478 // Not terminated, with headers | 445 " not-a-continuation\n" |
| 479 { | 446 "Bar: 2\n\n", |
| 480 "HTTP/1.0 200 OK\n" | 447 "HTTP/1.0 200 OK|" |
| 481 "Foo: 1\n" | 448 "Foo: 1|" |
| 482 "Bar: 2", | 449 "garbage|" |
| 483 | 450 " not-a-continuation|" |
| 484 "HTTP/1.0 200 OK|" | 451 "Bar: 2||", |
| 485 "Foo: 1|" | 452 }, |
| 486 "Bar: 2||" | 453 |
| 487 }, | 454 // Not a line continuation -- no valid name. |
| 488 | 455 { |
| 489 // Not a line continuation (VT) | 456 "HTTP/1.0 200 OK\n" |
| 490 { | 457 ": 1\n" |
| 491 "HTTP/1.0 200 OK\n" | 458 " garbage\n" |
| 492 "Foo: 1\n" | 459 "Bar: 2\n\n", |
| 493 "\vInvalidContinuation\n" | 460 "HTTP/1.0 200 OK|" |
| 494 "Bar: 2\n\n", | 461 ": 1|" |
| 495 | 462 " garbage|" |
| 496 "HTTP/1.0 200 OK|" | 463 "Bar: 2||", |
| 497 "Foo: 1|" | 464 }, |
| 498 "\vInvalidContinuation|" | 465 |
| 499 "Bar: 2||" | 466 // Not a line continuation -- no valid name (whitespace) |
| 500 }, | 467 { |
| 501 | 468 "HTTP/1.0 200 OK\n" |
| 502 // Not a line continuation (formfeed) | 469 " : 1\n" |
| 503 { | 470 " garbage\n" |
| 504 "HTTP/1.0 200 OK\n" | 471 "Bar: 2\n\n", |
| 505 "Foo: 1\n" | 472 "HTTP/1.0 200 OK|" |
| 506 "\fInvalidContinuation\n" | 473 " : 1|" |
| 507 "Bar: 2\n\n", | 474 " garbage|" |
| 508 | 475 "Bar: 2||", |
| 509 "HTTP/1.0 200 OK|" | 476 }, |
| 510 "Foo: 1|" | 477 |
| 511 "\fInvalidContinuation|" | 478 // Embed NULLs in the status line. They should not be understood |
| 512 "Bar: 2||" | 479 // as line separators. |
| 513 }, | 480 {"HTTP/1.0 200 OK|Bar2:0|Baz2:1\r\nFoo: 1\r\nBar: 2\r\n\r\n", |
| 514 | 481 "HTTP/1.0 200 OKBar2:0Baz2:1|Foo: 1|Bar: 2||"}, |
| 515 // Not a line continuation -- can't continue header names. | 482 |
| 516 { | 483 // Embed NULLs in a header line. They should not be understood as |
| 517 "HTTP/1.0 200 OK\n" | 484 // line separators. |
| 518 "Serv\n" | 485 {"HTTP/1.0 200 OK\nFoo: 1|Foo2: 3\nBar: 2\n\n", |
| 519 " er: Apache\n" | 486 "HTTP/1.0 200 OK|Foo: 1Foo2: 3|Bar: 2||"}, |
| 520 "\tInvalidContinuation\n" | 487 }; |
| 521 "Bar: 2\n\n", | |
| 522 | |
| 523 "HTTP/1.0 200 OK|" | |
| 524 "Serv|" | |
| 525 " er: Apache|" | |
| 526 "\tInvalidContinuation|" | |
| 527 "Bar: 2||" | |
| 528 }, | |
| 529 | |
| 530 // Not a line continuation -- no value to continue. | |
| 531 { | |
| 532 "HTTP/1.0 200 OK\n" | |
| 533 "Foo: 1\n" | |
| 534 "garbage\n" | |
| 535 " not-a-continuation\n" | |
| 536 "Bar: 2\n\n", | |
| 537 | |
| 538 "HTTP/1.0 200 OK|" | |
| 539 "Foo: 1|" | |
| 540 "garbage|" | |
| 541 " not-a-continuation|" | |
| 542 "Bar: 2||", | |
| 543 }, | |
| 544 | |
| 545 // Not a line continuation -- no valid name. | |
| 546 { | |
| 547 "HTTP/1.0 200 OK\n" | |
| 548 ": 1\n" | |
| 549 " garbage\n" | |
| 550 "Bar: 2\n\n", | |
| 551 | |
| 552 "HTTP/1.0 200 OK|" | |
| 553 ": 1|" | |
| 554 " garbage|" | |
| 555 "Bar: 2||", | |
| 556 }, | |
| 557 | |
| 558 // Not a line continuation -- no valid name (whitespace) | |
| 559 { | |
| 560 "HTTP/1.0 200 OK\n" | |
| 561 " : 1\n" | |
| 562 " garbage\n" | |
| 563 "Bar: 2\n\n", | |
| 564 | |
| 565 "HTTP/1.0 200 OK|" | |
| 566 " : 1|" | |
| 567 " garbage|" | |
| 568 "Bar: 2||", | |
| 569 }, | |
| 570 | |
| 571 // Embed NULLs in the status line. They should not be understood | |
| 572 // as line separators. | |
| 573 { | |
| 574 "HTTP/1.0 200 OK|Bar2:0|Baz2:1\r\nFoo: 1\r\nBar: 2\r\n\r\n", | |
| 575 "HTTP/1.0 200 OKBar2:0Baz2:1|Foo: 1|Bar: 2||" | |
| 576 }, | |
| 577 | |
| 578 // Embed NULLs in a header line. They should not be understood as | |
| 579 // line separators. | |
| 580 { | |
| 581 "HTTP/1.0 200 OK\nFoo: 1|Foo2: 3\nBar: 2\n\n", | |
| 582 "HTTP/1.0 200 OK|Foo: 1Foo2: 3|Bar: 2||" | |
| 583 }, | |
| 584 }; | |
| 585 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 488 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
| 586 std::string input = tests[i].input; | 489 std::string input = tests[i].input; |
| 587 std::replace(input.begin(), input.end(), '|', '\0'); | 490 std::replace(input.begin(), input.end(), '|', '\0'); |
| 588 std::string raw = HttpUtil::AssembleRawHeaders(input.data(), input.size()); | 491 std::string raw = HttpUtil::AssembleRawHeaders(input.data(), input.size()); |
| 589 std::replace(raw.begin(), raw.end(), '\0', '|'); | 492 std::replace(raw.begin(), raw.end(), '\0', '|'); |
| 590 EXPECT_EQ(tests[i].expected_result, raw); | 493 EXPECT_EQ(tests[i].expected_result, raw); |
| 591 } | 494 } |
| 592 } | 495 } |
| 593 | 496 |
| 594 // Test SpecForRequest() and PathForRequest(). | 497 // Test SpecForRequest() and PathForRequest(). |
| 595 TEST(HttpUtilTest, RequestUrlSanitize) { | 498 TEST(HttpUtilTest, RequestUrlSanitize) { |
| 596 struct { | 499 struct { |
| 597 const char* url; | 500 const char* url; |
| 598 const char* expected_spec; | 501 const char* expected_spec; |
| 599 const char* expected_path; | 502 const char* expected_path; |
| 600 } tests[] = { | 503 } tests[] = {{// Check that #hash is removed. |
| 601 { // Check that #hash is removed. | 504 "http://www.google.com:78/foobar?query=1#hash", |
| 602 "http://www.google.com:78/foobar?query=1#hash", | 505 "http://www.google.com:78/foobar?query=1", "/foobar?query=1"}, |
| 603 "http://www.google.com:78/foobar?query=1", | 506 {// The reference may itself contain # -- strip all of it. |
| 604 "/foobar?query=1" | 507 "http://192.168.0.1?query=1#hash#10#11#13#14", |
| 605 }, | 508 "http://192.168.0.1/?query=1", "/?query=1"}, |
| 606 { // The reference may itself contain # -- strip all of it. | 509 {// Strip username/password. |
| 607 "http://192.168.0.1?query=1#hash#10#11#13#14", | 510 "http://user:pass@google.com", "http://google.com/", "/"}, |
| 608 "http://192.168.0.1/?query=1", | 511 {// https scheme |
| 609 "/?query=1" | 512 "https://www.google.com:78/foobar?query=1#hash", |
| 610 }, | 513 "https://www.google.com:78/foobar?query=1", "/foobar?query=1"}, |
| 611 { // Strip username/password. | 514 {// WebSocket's ws scheme |
| 612 "http://user:pass@google.com", | 515 "ws://www.google.com:78/foobar?query=1#hash", |
| 613 "http://google.com/", | 516 "ws://www.google.com:78/foobar?query=1", "/foobar?query=1"}, |
| 614 "/" | 517 {// WebSocket's wss scheme |
| 615 }, | 518 "wss://www.google.com:78/foobar?query=1#hash", |
| 616 { // https scheme | 519 "wss://www.google.com:78/foobar?query=1", "/foobar?query=1"}}; |
| 617 "https://www.google.com:78/foobar?query=1#hash", | |
| 618 "https://www.google.com:78/foobar?query=1", | |
| 619 "/foobar?query=1" | |
| 620 }, | |
| 621 { // WebSocket's ws scheme | |
| 622 "ws://www.google.com:78/foobar?query=1#hash", | |
| 623 "ws://www.google.com:78/foobar?query=1", | |
| 624 "/foobar?query=1" | |
| 625 }, | |
| 626 { // WebSocket's wss scheme | |
| 627 "wss://www.google.com:78/foobar?query=1#hash", | |
| 628 "wss://www.google.com:78/foobar?query=1", | |
| 629 "/foobar?query=1" | |
| 630 } | |
| 631 }; | |
| 632 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 520 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
| 633 GURL url(GURL(tests[i].url)); | 521 GURL url(GURL(tests[i].url)); |
| 634 std::string expected_spec(tests[i].expected_spec); | 522 std::string expected_spec(tests[i].expected_spec); |
| 635 std::string expected_path(tests[i].expected_path); | 523 std::string expected_path(tests[i].expected_path); |
| 636 | 524 |
| 637 EXPECT_EQ(expected_spec, HttpUtil::SpecForRequest(url)); | 525 EXPECT_EQ(expected_spec, HttpUtil::SpecForRequest(url)); |
| 638 EXPECT_EQ(expected_path, HttpUtil::PathForRequest(url)); | 526 EXPECT_EQ(expected_path, HttpUtil::PathForRequest(url)); |
| 639 } | 527 } |
| 640 } | 528 } |
| 641 | 529 |
| 642 // Test SpecForRequest() for "ftp" scheme. | 530 // Test SpecForRequest() for "ftp" scheme. |
| 643 TEST(HttpUtilTest, SpecForRequestForUrlWithFtpScheme) { | 531 TEST(HttpUtilTest, SpecForRequestForUrlWithFtpScheme) { |
| 644 GURL ftp_url("ftp://user:pass@google.com/pub/chromium/"); | 532 GURL ftp_url("ftp://user:pass@google.com/pub/chromium/"); |
| 645 EXPECT_EQ("ftp://google.com/pub/chromium/", | 533 EXPECT_EQ("ftp://google.com/pub/chromium/", |
| 646 HttpUtil::SpecForRequest(ftp_url)); | 534 HttpUtil::SpecForRequest(ftp_url)); |
| 647 } | 535 } |
| 648 | 536 |
| 649 TEST(HttpUtilTest, GenerateAcceptLanguageHeader) { | 537 TEST(HttpUtilTest, GenerateAcceptLanguageHeader) { |
| 650 EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6"), | 538 EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6"), |
| 651 HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de")); | 539 HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de")); |
| 652 EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6,ko;q=0.4,zh-CN;q=0.2," | 540 EXPECT_EQ(std::string( |
| 653 "ja;q=0.2"), | 541 "en-US,fr;q=0.8,de;q=0.6,ko;q=0.4,zh-CN;q=0.2," |
| 542 "ja;q=0.2"), |
| 654 HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de,ko,zh-CN,ja")); | 543 HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de,ko,zh-CN,ja")); |
| 655 } | 544 } |
| 656 | 545 |
| 657 // HttpResponseHeadersTest.GetMimeType also tests ParseContentType. | 546 // HttpResponseHeadersTest.GetMimeType also tests ParseContentType. |
| 658 TEST(HttpUtilTest, ParseContentType) { | 547 TEST(HttpUtilTest, ParseContentType) { |
| 659 const struct { | 548 const struct { |
| 660 const char* content_type; | 549 const char* content_type; |
| 661 const char* expected_mime_type; | 550 const char* expected_mime_type; |
| 662 const char* expected_charset; | 551 const char* expected_charset; |
| 663 const bool expected_had_charset; | 552 const bool expected_had_charset; |
| 664 const char* expected_boundary; | 553 const char* expected_boundary; |
| 665 } tests[] = { | 554 } tests[] = { |
| 666 { "text/html; charset=utf-8", | 555 {"text/html; charset=utf-8", "text/html", "utf-8", true, ""}, |
| 667 "text/html", | 556 {"text/html; charset =utf-8", "text/html", "utf-8", true, ""}, |
| 668 "utf-8", | 557 {"text/html; charset= utf-8", "text/html", "utf-8", true, ""}, |
| 669 true, | 558 {"text/html; charset=utf-8 ", "text/html", "utf-8", true, ""}, |
| 670 "" | 559 {"text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs\"", "text/html", "", |
| 671 }, | 560 false, "\"WebKit-ada-df-dsf-adsfadsfs\""}, |
| 672 { "text/html; charset =utf-8", | 561 {"text/html; boundary =\"WebKit-ada-df-dsf-adsfadsfs\"", "text/html", |
| 673 "text/html", | 562 "", false, "\"WebKit-ada-df-dsf-adsfadsfs\""}, |
| 674 "utf-8", | 563 {"text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\"", "text/html", |
| 675 true, | 564 "", false, "\"WebKit-ada-df-dsf-adsfadsfs\""}, |
| 676 "" | 565 {"text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\" ", "text/html", |
| 677 }, | 566 "", false, "\"WebKit-ada-df-dsf-adsfadsfs\""}, |
| 678 { "text/html; charset= utf-8", | 567 {"text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs \"", "text/html", |
| 679 "text/html", | 568 "", false, "\"WebKit-ada-df-dsf-adsfadsfs \""}, |
| 680 "utf-8", | 569 {"text/html; boundary=WebKit-ada-df-dsf-adsfadsfs", "text/html", "", |
| 681 true, | 570 false, "WebKit-ada-df-dsf-adsfadsfs"}, |
| 682 "" | 571 // TODO(abarth): Add more interesting test cases. |
| 683 }, | 572 }; |
| 684 { "text/html; charset=utf-8 ", | |
| 685 "text/html", | |
| 686 "utf-8", | |
| 687 true, | |
| 688 "" | |
| 689 }, | |
| 690 { "text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs\"", | |
| 691 "text/html", | |
| 692 "", | |
| 693 false, | |
| 694 "\"WebKit-ada-df-dsf-adsfadsfs\"" | |
| 695 }, | |
| 696 { "text/html; boundary =\"WebKit-ada-df-dsf-adsfadsfs\"", | |
| 697 "text/html", | |
| 698 "", | |
| 699 false, | |
| 700 "\"WebKit-ada-df-dsf-adsfadsfs\"" | |
| 701 }, | |
| 702 { "text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\"", | |
| 703 "text/html", | |
| 704 "", | |
| 705 false, | |
| 706 "\"WebKit-ada-df-dsf-adsfadsfs\"" | |
| 707 }, | |
| 708 { "text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\" ", | |
| 709 "text/html", | |
| 710 "", | |
| 711 false, | |
| 712 "\"WebKit-ada-df-dsf-adsfadsfs\"" | |
| 713 }, | |
| 714 { "text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs \"", | |
| 715 "text/html", | |
| 716 "", | |
| 717 false, | |
| 718 "\"WebKit-ada-df-dsf-adsfadsfs \"" | |
| 719 }, | |
| 720 { "text/html; boundary=WebKit-ada-df-dsf-adsfadsfs", | |
| 721 "text/html", | |
| 722 "", | |
| 723 false, | |
| 724 "WebKit-ada-df-dsf-adsfadsfs" | |
| 725 }, | |
| 726 // TODO(abarth): Add more interesting test cases. | |
| 727 }; | |
| 728 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 573 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
| 729 std::string mime_type; | 574 std::string mime_type; |
| 730 std::string charset; | 575 std::string charset; |
| 731 bool had_charset = false; | 576 bool had_charset = false; |
| 732 std::string boundary; | 577 std::string boundary; |
| 733 net::HttpUtil::ParseContentType(tests[i].content_type, &mime_type, | 578 net::HttpUtil::ParseContentType( |
| 734 &charset, &had_charset, &boundary); | 579 tests[i].content_type, &mime_type, &charset, &had_charset, &boundary); |
| 735 EXPECT_EQ(tests[i].expected_mime_type, mime_type) << "i=" << i; | 580 EXPECT_EQ(tests[i].expected_mime_type, mime_type) << "i=" << i; |
| 736 EXPECT_EQ(tests[i].expected_charset, charset) << "i=" << i; | 581 EXPECT_EQ(tests[i].expected_charset, charset) << "i=" << i; |
| 737 EXPECT_EQ(tests[i].expected_had_charset, had_charset) << "i=" << i; | 582 EXPECT_EQ(tests[i].expected_had_charset, had_charset) << "i=" << i; |
| 738 EXPECT_EQ(tests[i].expected_boundary, boundary) << "i=" << i; | 583 EXPECT_EQ(tests[i].expected_boundary, boundary) << "i=" << i; |
| 739 } | 584 } |
| 740 } | 585 } |
| 741 | 586 |
| 742 TEST(HttpUtilTest, ParseRanges) { | 587 TEST(HttpUtilTest, ParseRanges) { |
| 743 const struct { | 588 const struct { |
| 744 const char* headers; | 589 const char* headers; |
| 745 bool expected_return_value; | 590 bool expected_return_value; |
| 746 size_t expected_ranges_size; | 591 size_t expected_ranges_size; |
| 747 const struct { | 592 const struct { |
| 748 int64 expected_first_byte_position; | 593 int64 expected_first_byte_position; |
| 749 int64 expected_last_byte_position; | 594 int64 expected_last_byte_position; |
| 750 int64 expected_suffix_length; | 595 int64 expected_suffix_length; |
| 751 } expected_ranges[10]; | 596 } expected_ranges[10]; |
| 752 } tests[] = { | 597 } tests[] = { |
| 753 { "Range: bytes=0-10", | 598 {"Range: bytes=0-10", |
| 754 true, | 599 true, |
| 755 1, | 600 1, |
| 756 { {0, 10, -1}, } | 601 { |
| 757 }, | 602 {0, 10, -1}, |
| 758 { "Range: bytes=10-0", | 603 }}, |
| 759 false, | 604 {"Range: bytes=10-0", false, 0, {}}, |
| 760 0, | 605 {"Range: BytES=0-10", |
| 761 {} | 606 true, |
| 762 }, | 607 1, |
| 763 { "Range: BytES=0-10", | 608 { |
| 764 true, | 609 {0, 10, -1}, |
| 765 1, | 610 }}, |
| 766 { {0, 10, -1}, } | 611 {"Range: megabytes=0-10", false, 0, {}}, |
| 767 }, | 612 {"Range: bytes0-10", false, 0, {}}, |
| 768 { "Range: megabytes=0-10", | 613 {"Range: bytes=0-0,0-10,10-20,100-200,100-,-200", |
| 769 false, | 614 true, |
| 770 0, | 615 6, |
| 771 {} | 616 { |
| 772 }, | 617 {0, 0, -1}, |
| 773 { "Range: bytes0-10", | 618 {0, 10, -1}, |
| 774 false, | 619 {10, 20, -1}, |
| 775 0, | 620 {100, 200, -1}, |
| 776 {} | 621 {100, -1, -1}, |
| 777 }, | 622 {-1, -1, 200}, |
| 778 { "Range: bytes=0-0,0-10,10-20,100-200,100-,-200", | 623 }}, |
| 779 true, | 624 {"Range: bytes=0-10\r\n" |
| 780 6, | 625 "Range: bytes=0-10,10-20,100-200,100-,-200", |
| 781 { {0, 0, -1}, | 626 true, |
| 782 {0, 10, -1}, | 627 1, |
| 783 {10, 20, -1}, | 628 {{0, 10, -1}}}, |
| 784 {100, 200, -1}, | 629 {"Range: bytes=", false, 0, {}}, |
| 785 {100, -1, -1}, | 630 {"Range: bytes=-", false, 0, {}}, |
| 786 {-1, -1, 200}, | 631 {"Range: bytes=0-10-", false, 0, {}}, |
| 787 } | 632 {"Range: bytes=-0-10", false, 0, {}}, |
| 788 }, | 633 {"Range: bytes =0-10\r\n", true, 1, {{0, 10, -1}}}, |
| 789 { "Range: bytes=0-10\r\n" | 634 {"Range: bytes= 0-10 \r\n", true, 1, {{0, 10, -1}}}, |
| 790 "Range: bytes=0-10,10-20,100-200,100-,-200", | 635 {"Range: bytes = 0 - 10 \r\n", true, 1, {{0, 10, -1}}}, |
| 791 true, | 636 {"Range: bytes= 0-1 0\r\n", false, 0, {}}, |
| 792 1, | 637 {"Range: bytes= 0- -10\r\n", false, 0, {}}, |
| 793 { {0, 10, -1} | 638 {"Range: bytes= 0 - 1 , 10 -20, 100- 200 , 100-, -200 \r\n", |
| 794 } | 639 true, |
| 795 }, | 640 5, |
| 796 { "Range: bytes=", | 641 { |
| 797 false, | 642 {0, 1, -1}, |
| 798 0, | 643 {10, 20, -1}, |
| 799 {} | 644 {100, 200, -1}, |
| 800 }, | 645 {100, -1, -1}, |
| 801 { "Range: bytes=-", | 646 {-1, -1, 200}, |
| 802 false, | 647 }}, |
| 803 0, | 648 }; |
| 804 {} | |
| 805 }, | |
| 806 { "Range: bytes=0-10-", | |
| 807 false, | |
| 808 0, | |
| 809 {} | |
| 810 }, | |
| 811 { "Range: bytes=-0-10", | |
| 812 false, | |
| 813 0, | |
| 814 {} | |
| 815 }, | |
| 816 { "Range: bytes =0-10\r\n", | |
| 817 true, | |
| 818 1, | |
| 819 { {0, 10, -1} | |
| 820 } | |
| 821 }, | |
| 822 { "Range: bytes= 0-10 \r\n", | |
| 823 true, | |
| 824 1, | |
| 825 { {0, 10, -1} | |
| 826 } | |
| 827 }, | |
| 828 { "Range: bytes = 0 - 10 \r\n", | |
| 829 true, | |
| 830 1, | |
| 831 { {0, 10, -1} | |
| 832 } | |
| 833 }, | |
| 834 { "Range: bytes= 0-1 0\r\n", | |
| 835 false, | |
| 836 0, | |
| 837 {} | |
| 838 }, | |
| 839 { "Range: bytes= 0- -10\r\n", | |
| 840 false, | |
| 841 0, | |
| 842 {} | |
| 843 }, | |
| 844 { "Range: bytes= 0 - 1 , 10 -20, 100- 200 , 100-, -200 \r\n", | |
| 845 true, | |
| 846 5, | |
| 847 { {0, 1, -1}, | |
| 848 {10, 20, -1}, | |
| 849 {100, 200, -1}, | |
| 850 {100, -1, -1}, | |
| 851 {-1, -1, 200}, | |
| 852 } | |
| 853 }, | |
| 854 }; | |
| 855 | 649 |
| 856 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 650 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
| 857 std::vector<net::HttpByteRange> ranges; | 651 std::vector<net::HttpByteRange> ranges; |
| 858 bool return_value = HttpUtil::ParseRanges(std::string(tests[i].headers), | 652 bool return_value = |
| 859 &ranges); | 653 HttpUtil::ParseRanges(std::string(tests[i].headers), &ranges); |
| 860 EXPECT_EQ(tests[i].expected_return_value, return_value); | 654 EXPECT_EQ(tests[i].expected_return_value, return_value); |
| 861 if (return_value) { | 655 if (return_value) { |
| 862 EXPECT_EQ(tests[i].expected_ranges_size, ranges.size()); | 656 EXPECT_EQ(tests[i].expected_ranges_size, ranges.size()); |
| 863 for (size_t j = 0; j < ranges.size(); ++j) { | 657 for (size_t j = 0; j < ranges.size(); ++j) { |
| 864 EXPECT_EQ(tests[i].expected_ranges[j].expected_first_byte_position, | 658 EXPECT_EQ(tests[i].expected_ranges[j].expected_first_byte_position, |
| 865 ranges[j].first_byte_position()); | 659 ranges[j].first_byte_position()); |
| 866 EXPECT_EQ(tests[i].expected_ranges[j].expected_last_byte_position, | 660 EXPECT_EQ(tests[i].expected_ranges[j].expected_last_byte_position, |
| 867 ranges[j].last_byte_position()); | 661 ranges[j].last_byte_position()); |
| 868 EXPECT_EQ(tests[i].expected_ranges[j].expected_suffix_length, | 662 EXPECT_EQ(tests[i].expected_ranges[j].expected_suffix_length, |
| 869 ranges[j].suffix_length()); | 663 ranges[j].suffix_length()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 881 if (!expect_valid) { | 675 if (!expect_valid) { |
| 882 return; | 676 return; |
| 883 } | 677 } |
| 884 | 678 |
| 885 // Let's make sure that these never change (i.e., when a quoted value is | 679 // Let's make sure that these never change (i.e., when a quoted value is |
| 886 // unquoted, it should be cached on the first calls and not regenerated | 680 // unquoted, it should be cached on the first calls and not regenerated |
| 887 // later). | 681 // later). |
| 888 std::string::const_iterator first_value_begin = parser->value_begin(); | 682 std::string::const_iterator first_value_begin = parser->value_begin(); |
| 889 std::string::const_iterator first_value_end = parser->value_end(); | 683 std::string::const_iterator first_value_end = parser->value_end(); |
| 890 | 684 |
| 891 ASSERT_EQ(expected_name, std::string(parser->name_begin(), | 685 ASSERT_EQ(expected_name, |
| 892 parser->name_end())); | 686 std::string(parser->name_begin(), parser->name_end())); |
| 893 ASSERT_EQ(expected_name, parser->name()); | 687 ASSERT_EQ(expected_name, parser->name()); |
| 894 ASSERT_EQ(expected_value, std::string(parser->value_begin(), | 688 ASSERT_EQ(expected_value, |
| 895 parser->value_end())); | 689 std::string(parser->value_begin(), parser->value_end())); |
| 896 ASSERT_EQ(expected_value, parser->value()); | 690 ASSERT_EQ(expected_value, parser->value()); |
| 897 | 691 |
| 898 // Make sure they didn't/don't change. | 692 // Make sure they didn't/don't change. |
| 899 ASSERT_TRUE(first_value_begin == parser->value_begin()); | 693 ASSERT_TRUE(first_value_begin == parser->value_begin()); |
| 900 ASSERT_TRUE(first_value_end == parser->value_end()); | 694 ASSERT_TRUE(first_value_end == parser->value_end()); |
| 901 } | 695 } |
| 902 | 696 |
| 903 void CheckNextNameValuePair(HttpUtil::NameValuePairsIterator* parser, | 697 void CheckNextNameValuePair(HttpUtil::NameValuePairsIterator* parser, |
| 904 bool expect_next, | 698 bool expect_next, |
| 905 bool expect_valid, | 699 bool expect_valid, |
| 906 std::string expected_name, | 700 std::string expected_name, |
| 907 std::string expected_value) { | 701 std::string expected_value) { |
| 908 ASSERT_EQ(expect_next, parser->GetNext()); | 702 ASSERT_EQ(expect_next, parser->GetNext()); |
| 909 ASSERT_EQ(expect_valid, parser->valid()); | 703 ASSERT_EQ(expect_valid, parser->valid()); |
| 910 if (!expect_next || !expect_valid) { | 704 if (!expect_next || !expect_valid) { |
| 911 return; | 705 return; |
| 912 } | 706 } |
| 913 | 707 |
| 914 CheckCurrentNameValuePair(parser, | 708 CheckCurrentNameValuePair( |
| 915 expect_valid, | 709 parser, expect_valid, expected_name, expected_value); |
| 916 expected_name, | |
| 917 expected_value); | |
| 918 } | 710 } |
| 919 | 711 |
| 920 void CheckInvalidNameValuePair(std::string valid_part, | 712 void CheckInvalidNameValuePair(std::string valid_part, |
| 921 std::string invalid_part) { | 713 std::string invalid_part) { |
| 922 std::string whole_string = valid_part + invalid_part; | 714 std::string whole_string = valid_part + invalid_part; |
| 923 | 715 |
| 924 HttpUtil::NameValuePairsIterator valid_parser(valid_part.begin(), | 716 HttpUtil::NameValuePairsIterator valid_parser( |
| 925 valid_part.end(), | 717 valid_part.begin(), valid_part.end(), ';'); |
| 926 ';'); | 718 HttpUtil::NameValuePairsIterator invalid_parser( |
| 927 HttpUtil::NameValuePairsIterator invalid_parser(whole_string.begin(), | 719 whole_string.begin(), whole_string.end(), ';'); |
| 928 whole_string.end(), | |
| 929 ';'); | |
| 930 | 720 |
| 931 ASSERT_TRUE(valid_parser.valid()); | 721 ASSERT_TRUE(valid_parser.valid()); |
| 932 ASSERT_TRUE(invalid_parser.valid()); | 722 ASSERT_TRUE(invalid_parser.valid()); |
| 933 | 723 |
| 934 // Both parsers should return all the same values until "valid_parser" is | 724 // Both parsers should return all the same values until "valid_parser" is |
| 935 // exhausted. | 725 // exhausted. |
| 936 while (valid_parser.GetNext()) { | 726 while (valid_parser.GetNext()) { |
| 937 ASSERT_TRUE(invalid_parser.GetNext()); | 727 ASSERT_TRUE(invalid_parser.GetNext()); |
| 938 ASSERT_TRUE(valid_parser.valid()); | 728 ASSERT_TRUE(valid_parser.valid()); |
| 939 ASSERT_TRUE(invalid_parser.valid()); | 729 ASSERT_TRUE(invalid_parser.valid()); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 TEST(HttpUtilTest, NameValuePairsIteratorEmptyInput) { | 780 TEST(HttpUtilTest, NameValuePairsIteratorEmptyInput) { |
| 991 std::string data; | 781 std::string data; |
| 992 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';'); | 782 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';'); |
| 993 | 783 |
| 994 EXPECT_TRUE(parser.valid()); | 784 EXPECT_TRUE(parser.valid()); |
| 995 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair( | 785 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair( |
| 996 &parser, false, true, std::string(), std::string())); | 786 &parser, false, true, std::string(), std::string())); |
| 997 } | 787 } |
| 998 | 788 |
| 999 TEST(HttpUtilTest, NameValuePairsIterator) { | 789 TEST(HttpUtilTest, NameValuePairsIterator) { |
| 1000 std::string data = "alpha=1; beta= 2 ;cappa =' 3; ';" | 790 std::string data = |
| 1001 "delta= \" \\\"4\\\" \"; e= \" '5'\"; e=6;" | 791 "alpha=1; beta= 2 ;cappa =' 3; ';" |
| 1002 "f='\\'\\h\\e\\l\\l\\o\\ \\w\\o\\r\\l\\d\\'';" | 792 "delta= \" \\\"4\\\" \"; e= \" '5'\"; e=6;" |
| 1003 "g=''; h='hello'"; | 793 "f='\\'\\h\\e\\l\\l\\o\\ \\w\\o\\r\\l\\d\\'';" |
| 794 "g=''; h='hello'"; |
| 1004 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';'); | 795 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';'); |
| 1005 EXPECT_TRUE(parser.valid()); | 796 EXPECT_TRUE(parser.valid()); |
| 1006 | 797 |
| 1007 ASSERT_NO_FATAL_FAILURE( | 798 ASSERT_NO_FATAL_FAILURE( |
| 1008 CheckNextNameValuePair(&parser, true, true, "alpha", "1")); | 799 CheckNextNameValuePair(&parser, true, true, "alpha", "1")); |
| 1009 ASSERT_NO_FATAL_FAILURE( | 800 ASSERT_NO_FATAL_FAILURE( |
| 1010 CheckNextNameValuePair(&parser, true, true, "beta", "2")); | 801 CheckNextNameValuePair(&parser, true, true, "beta", "2")); |
| 1011 ASSERT_NO_FATAL_FAILURE( | 802 ASSERT_NO_FATAL_FAILURE( |
| 1012 CheckNextNameValuePair(&parser, true, true, "cappa", " 3; ")); | 803 CheckNextNameValuePair(&parser, true, true, "cappa", " 3; ")); |
| 1013 ASSERT_NO_FATAL_FAILURE( | 804 ASSERT_NO_FATAL_FAILURE( |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1026 &parser, false, true, std::string(), std::string())); | 817 &parser, false, true, std::string(), std::string())); |
| 1027 } | 818 } |
| 1028 | 819 |
| 1029 TEST(HttpUtilTest, NameValuePairsIteratorIllegalInputs) { | 820 TEST(HttpUtilTest, NameValuePairsIteratorIllegalInputs) { |
| 1030 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; beta")); | 821 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; beta")); |
| 1031 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "beta")); | 822 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "beta")); |
| 1032 | 823 |
| 1033 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; 'beta'=2")); | 824 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; 'beta'=2")); |
| 1034 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "'beta'=2")); | 825 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "'beta'=2")); |
| 1035 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";beta=")); | 826 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";beta=")); |
| 1036 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", | 827 ASSERT_NO_FATAL_FAILURE( |
| 1037 ";beta=;cappa=2")); | 828 CheckInvalidNameValuePair("alpha=1", ";beta=;cappa=2")); |
| 1038 | 829 |
| 1039 // According to the spec this is an error, but it doesn't seem appropriate to | 830 // According to the spec this is an error, but it doesn't seem appropriate to |
| 1040 // change our behaviour to be less permissive at this time. | 831 // change our behaviour to be less permissive at this time. |
| 1041 // See NameValuePairsIteratorExtraSeparators test | 832 // See NameValuePairsIteratorExtraSeparators test |
| 1042 // ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";; beta=2")); | 833 // ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";; beta=2")); |
| 1043 } | 834 } |
| 1044 | 835 |
| 1045 // If we are going to support extra separators against the spec, let's just make | 836 // If we are going to support extra separators against the spec, let's just make |
| 1046 // sure they work rationally. | 837 // sure they work rationally. |
| 1047 TEST(HttpUtilTest, NameValuePairsIteratorExtraSeparators) { | 838 TEST(HttpUtilTest, NameValuePairsIteratorExtraSeparators) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1064 TEST(HttpUtilTest, NameValuePairsIteratorMissingEndQuote) { | 855 TEST(HttpUtilTest, NameValuePairsIteratorMissingEndQuote) { |
| 1065 std::string data = "name='value"; | 856 std::string data = "name='value"; |
| 1066 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';'); | 857 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';'); |
| 1067 EXPECT_TRUE(parser.valid()); | 858 EXPECT_TRUE(parser.valid()); |
| 1068 | 859 |
| 1069 ASSERT_NO_FATAL_FAILURE( | 860 ASSERT_NO_FATAL_FAILURE( |
| 1070 CheckNextNameValuePair(&parser, true, true, "name", "value")); | 861 CheckNextNameValuePair(&parser, true, true, "name", "value")); |
| 1071 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair( | 862 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair( |
| 1072 &parser, false, true, std::string(), std::string())); | 863 &parser, false, true, std::string(), std::string())); |
| 1073 } | 864 } |
| OLD | NEW |