http_util_unittest.cc 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711
  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
  3. // found in the LICENSE file.
  4. #include "net/http/http_util.h"
  5. #include <algorithm>
  6. #include <limits>
  7. #include "base/strings/string_util.h"
  8. #include "base/time/time.h"
  9. #include "testing/gtest/include/gtest/gtest.h"
  10. namespace net {
  11. TEST(HttpUtilTest, IsSafeHeader) {
  12. static const char* const unsafe_headers[] = {
  13. "sec-",
  14. "sEc-",
  15. "sec-foo",
  16. "sEc-FoO",
  17. "proxy-",
  18. "pRoXy-",
  19. "proxy-foo",
  20. "pRoXy-FoO",
  21. "accept-charset",
  22. "accept-encoding",
  23. "access-control-request-headers",
  24. "access-control-request-method",
  25. "connection",
  26. "content-length",
  27. "cookie",
  28. "cookie2",
  29. "date",
  30. "dnt",
  31. "expect",
  32. "host",
  33. "keep-alive",
  34. "origin",
  35. "referer",
  36. "set-cookie",
  37. "te",
  38. "trailer",
  39. "transfer-encoding",
  40. "upgrade",
  41. "user-agent",
  42. "via",
  43. };
  44. for (const auto* unsafe_header : unsafe_headers) {
  45. EXPECT_FALSE(HttpUtil::IsSafeHeader(unsafe_header)) << unsafe_header;
  46. EXPECT_FALSE(HttpUtil::IsSafeHeader(base::ToUpperASCII(unsafe_header)))
  47. << unsafe_header;
  48. }
  49. static const char* const safe_headers[] = {
  50. "foo",
  51. "x-",
  52. "x-foo",
  53. "content-disposition",
  54. "update",
  55. "accept-charseta",
  56. "accept_charset",
  57. "accept-encodinga",
  58. "accept_encoding",
  59. "access-control-request-headersa",
  60. "access-control-request-header",
  61. "access_control_request_header",
  62. "access-control-request-methoda",
  63. "access_control_request_method",
  64. "connectiona",
  65. "content-lengtha",
  66. "content_length",
  67. "content-transfer-encoding",
  68. "cookiea",
  69. "cookie2a",
  70. "cookie3",
  71. "content-transfer-encodinga",
  72. "content_transfer_encoding",
  73. "datea",
  74. "expecta",
  75. "hosta",
  76. "keep-alivea",
  77. "keep_alive",
  78. "origina",
  79. "referera",
  80. "referrer",
  81. "tea",
  82. "trailera",
  83. "transfer-encodinga",
  84. "transfer_encoding",
  85. "upgradea",
  86. "user-agenta",
  87. "user_agent",
  88. "viaa",
  89. };
  90. for (const auto* safe_header : safe_headers) {
  91. EXPECT_TRUE(HttpUtil::IsSafeHeader(safe_header)) << safe_header;
  92. EXPECT_TRUE(HttpUtil::IsSafeHeader(base::ToUpperASCII(safe_header)))
  93. << safe_header;
  94. }
  95. }
  96. TEST(HttpUtilTest, HeadersIterator) {
  97. std::string headers = "foo: 1\t\r\nbar: hello world\r\nbaz: 3 \r\n";
  98. HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
  99. ASSERT_TRUE(it.GetNext());
  100. EXPECT_EQ(std::string("foo"), it.name());
  101. EXPECT_EQ(std::string("1"), it.values());
  102. ASSERT_TRUE(it.GetNext());
  103. EXPECT_EQ(std::string("bar"), it.name());
  104. EXPECT_EQ(std::string("hello world"), it.values());
  105. ASSERT_TRUE(it.GetNext());
  106. EXPECT_EQ(std::string("baz"), it.name());
  107. EXPECT_EQ(std::string("3"), it.values());
  108. EXPECT_FALSE(it.GetNext());
  109. }
  110. TEST(HttpUtilTest, HeadersIterator_MalformedLine) {
  111. std::string headers = "foo: 1\n: 2\n3\nbar: 4";
  112. HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n");
  113. ASSERT_TRUE(it.GetNext());
  114. EXPECT_EQ(std::string("foo"), it.name());
  115. EXPECT_EQ(std::string("1"), it.values());
  116. ASSERT_TRUE(it.GetNext());
  117. EXPECT_EQ(std::string("bar"), it.name());
  118. EXPECT_EQ(std::string("4"), it.values());
  119. EXPECT_FALSE(it.GetNext());
  120. }
  121. TEST(HttpUtilTest, HeadersIterator_MalformedName) {
  122. std::string headers = "[ignore me] /: 3\r\n";
  123. HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
  124. EXPECT_FALSE(it.GetNext());
  125. }
  126. TEST(HttpUtilTest, HeadersIterator_MalformedNameFollowedByValidLine) {
  127. std::string headers = "[ignore me] /: 3\r\nbar: 4\n";
  128. HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
  129. ASSERT_TRUE(it.GetNext());
  130. EXPECT_EQ(std::string("bar"), it.name());
  131. EXPECT_EQ(std::string("4"), it.values());
  132. EXPECT_FALSE(it.GetNext());
  133. }
  134. TEST(HttpUtilTest, HeadersIterator_AdvanceTo) {
  135. std::string headers = "foo: 1\r\n: 2\r\n3\r\nbar: 4";
  136. HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
  137. EXPECT_TRUE(it.AdvanceTo("foo"));
  138. EXPECT_EQ("foo", it.name());
  139. EXPECT_TRUE(it.AdvanceTo("bar"));
  140. EXPECT_EQ("bar", it.name());
  141. EXPECT_FALSE(it.AdvanceTo("blat"));
  142. EXPECT_FALSE(it.GetNext()); // should be at end of headers
  143. }
  144. TEST(HttpUtilTest, HeadersIterator_Reset) {
  145. std::string headers = "foo: 1\r\n: 2\r\n3\r\nbar: 4";
  146. HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
  147. // Search past "foo".
  148. EXPECT_TRUE(it.AdvanceTo("bar"));
  149. // Now try advancing to "foo". This time it should fail since the iterator
  150. // position is past it.
  151. EXPECT_FALSE(it.AdvanceTo("foo"));
  152. it.Reset();
  153. // Now that we reset the iterator position, we should find 'foo'
  154. EXPECT_TRUE(it.AdvanceTo("foo"));
  155. }
  156. TEST(HttpUtilTest, ValuesIterator) {
  157. std::string values = " must-revalidate, no-cache=\"foo, bar\"\t, private ";
  158. HttpUtil::ValuesIterator it(values.begin(), values.end(), ',',
  159. true /* ignore_empty_values */);
  160. ASSERT_TRUE(it.GetNext());
  161. EXPECT_EQ(std::string("must-revalidate"), it.value());
  162. ASSERT_TRUE(it.GetNext());
  163. EXPECT_EQ(std::string("no-cache=\"foo, bar\""), it.value());
  164. ASSERT_TRUE(it.GetNext());
  165. EXPECT_EQ(std::string("private"), it.value());
  166. EXPECT_FALSE(it.GetNext());
  167. }
  168. TEST(HttpUtilTest, ValuesIterator_EmptyValues) {
  169. std::string values = ", foopy , \t ,,,";
  170. HttpUtil::ValuesIterator it(values.begin(), values.end(), ',',
  171. true /* ignore_empty_values */);
  172. ASSERT_TRUE(it.GetNext());
  173. EXPECT_EQ(std::string("foopy"), it.value());
  174. EXPECT_FALSE(it.GetNext());
  175. HttpUtil::ValuesIterator it_with_empty_values(
  176. values.begin(), values.end(), ',', false /* ignore_empty_values */);
  177. ASSERT_TRUE(it_with_empty_values.GetNext());
  178. EXPECT_EQ(std::string(""), it_with_empty_values.value());
  179. ASSERT_TRUE(it_with_empty_values.GetNext());
  180. EXPECT_EQ(std::string("foopy"), it_with_empty_values.value());
  181. ASSERT_TRUE(it_with_empty_values.GetNext());
  182. EXPECT_EQ(std::string(""), it_with_empty_values.value());
  183. ASSERT_TRUE(it_with_empty_values.GetNext());
  184. EXPECT_EQ(std::string(""), it_with_empty_values.value());
  185. ASSERT_TRUE(it_with_empty_values.GetNext());
  186. EXPECT_EQ(std::string(""), it_with_empty_values.value());
  187. ASSERT_TRUE(it_with_empty_values.GetNext());
  188. EXPECT_EQ(std::string(""), it_with_empty_values.value());
  189. EXPECT_FALSE(it_with_empty_values.GetNext());
  190. }
  191. TEST(HttpUtilTest, ValuesIterator_Blanks) {
  192. std::string values = " \t ";
  193. HttpUtil::ValuesIterator it(values.begin(), values.end(), ',',
  194. true /* ignore_empty_values */);
  195. EXPECT_FALSE(it.GetNext());
  196. HttpUtil::ValuesIterator it_with_empty_values(
  197. values.begin(), values.end(), ',', false /* ignore_empty_values */);
  198. ASSERT_TRUE(it_with_empty_values.GetNext());
  199. EXPECT_EQ(std::string(""), it_with_empty_values.value());
  200. EXPECT_FALSE(it_with_empty_values.GetNext());
  201. }
  202. TEST(HttpUtilTest, Unquote) {
  203. // Replace <backslash> " with ".
  204. EXPECT_STREQ("xyz\"abc", HttpUtil::Unquote("\"xyz\\\"abc\"").c_str());
  205. // Replace <backslash> <backslash> with <backslash>
  206. EXPECT_STREQ("xyz\\abc", HttpUtil::Unquote("\"xyz\\\\abc\"").c_str());
  207. EXPECT_STREQ("xyz\\\\\\abc",
  208. HttpUtil::Unquote("\"xyz\\\\\\\\\\\\abc\"").c_str());
  209. // Replace <backslash> X with X
  210. EXPECT_STREQ("xyzXabc", HttpUtil::Unquote("\"xyz\\Xabc\"").c_str());
  211. // Act as identity function on unquoted inputs.
  212. EXPECT_STREQ("X", HttpUtil::Unquote("X").c_str());
  213. EXPECT_STREQ("\"", HttpUtil::Unquote("\"").c_str());
  214. // Allow quotes in the middle of the input.
  215. EXPECT_STREQ("foo\"bar", HttpUtil::Unquote("\"foo\"bar\"").c_str());
  216. // Allow the final quote to be escaped.
  217. EXPECT_STREQ("foo", HttpUtil::Unquote("\"foo\\\"").c_str());
  218. }
  219. TEST(HttpUtilTest, StrictUnquote) {
  220. std::string out;
  221. // Replace <backslash> " with ".
  222. EXPECT_TRUE(HttpUtil::StrictUnquote("\"xyz\\\"abc\"", &out));
  223. EXPECT_STREQ("xyz\"abc", out.c_str());
  224. // Replace <backslash> <backslash> with <backslash>.
  225. EXPECT_TRUE(HttpUtil::StrictUnquote("\"xyz\\\\abc\"", &out));
  226. EXPECT_STREQ("xyz\\abc", out.c_str());
  227. EXPECT_TRUE(HttpUtil::StrictUnquote("\"xyz\\\\\\\\\\\\abc\"", &out));
  228. EXPECT_STREQ("xyz\\\\\\abc", out.c_str());
  229. // Replace <backslash> X with X.
  230. EXPECT_TRUE(HttpUtil::StrictUnquote("\"xyz\\Xabc\"", &out));
  231. EXPECT_STREQ("xyzXabc", out.c_str());
  232. // Empty quoted string.
  233. EXPECT_TRUE(HttpUtil::StrictUnquote("\"\"", &out));
  234. EXPECT_STREQ("", out.c_str());
  235. // Return false on unquoted inputs.
  236. EXPECT_FALSE(HttpUtil::StrictUnquote("X", &out));
  237. EXPECT_FALSE(HttpUtil::StrictUnquote("", &out));
  238. // Return false on mismatched quotes.
  239. EXPECT_FALSE(HttpUtil::StrictUnquote("\"", &out));
  240. EXPECT_FALSE(HttpUtil::StrictUnquote("\"xyz", &out));
  241. EXPECT_FALSE(HttpUtil::StrictUnquote("\"abc'", &out));
  242. // Return false on escaped terminal quote.
  243. EXPECT_FALSE(HttpUtil::StrictUnquote("\"abc\\\"", &out));
  244. EXPECT_FALSE(HttpUtil::StrictUnquote("\"\\\"", &out));
  245. // Allow escaped backslash before terminal quote.
  246. EXPECT_TRUE(HttpUtil::StrictUnquote("\"\\\\\"", &out));
  247. EXPECT_STREQ("\\", out.c_str());
  248. // Don't allow single quotes to act as quote marks.
  249. EXPECT_FALSE(HttpUtil::StrictUnquote("'x\"'", &out));
  250. EXPECT_TRUE(HttpUtil::StrictUnquote("\"x'\"", &out));
  251. EXPECT_STREQ("x'", out.c_str());
  252. EXPECT_FALSE(HttpUtil::StrictUnquote("''", &out));
  253. }
  254. TEST(HttpUtilTest, Quote) {
  255. EXPECT_STREQ("\"xyz\\\"abc\"", HttpUtil::Quote("xyz\"abc").c_str());
  256. // Replace <backslash> <backslash> with <backslash>
  257. EXPECT_STREQ("\"xyz\\\\abc\"", HttpUtil::Quote("xyz\\abc").c_str());
  258. // Replace <backslash> X with X
  259. EXPECT_STREQ("\"xyzXabc\"", HttpUtil::Quote("xyzXabc").c_str());
  260. }
  261. TEST(HttpUtilTest, LocateEndOfHeaders) {
  262. struct {
  263. const char* const input;
  264. size_t expected_result;
  265. } tests[] = {
  266. {"\r\n", std::string::npos},
  267. {"\n", std::string::npos},
  268. {"\r", std::string::npos},
  269. {"foo", std::string::npos},
  270. {"\r\n\r\n", 4},
  271. {"foo\r\nbar\r\n\r\n", 12},
  272. {"foo\nbar\n\n", 9},
  273. {"foo\r\nbar\r\n\r\njunk", 12},
  274. {"foo\nbar\n\njunk", 9},
  275. {"foo\nbar\n\r\njunk", 10},
  276. {"foo\nbar\r\n\njunk", 10},
  277. };
  278. for (const auto& test : tests) {
  279. size_t input_len = strlen(test.input);
  280. size_t eoh = HttpUtil::LocateEndOfHeaders(test.input, input_len);
  281. EXPECT_EQ(test.expected_result, eoh);
  282. }
  283. }
  284. TEST(HttpUtilTest, LocateEndOfAdditionalHeaders) {
  285. struct {
  286. const char* const input;
  287. size_t expected_result;
  288. } tests[] = {
  289. {"\r\n", 2},
  290. {"\n", 1},
  291. {"\r", std::string::npos},
  292. {"foo", std::string::npos},
  293. {"\r\n\r\n", 2},
  294. {"foo\r\nbar\r\n\r\n", 12},
  295. {"foo\nbar\n\n", 9},
  296. {"foo\r\nbar\r\n\r\njunk", 12},
  297. {"foo\nbar\n\njunk", 9},
  298. {"foo\nbar\n\r\njunk", 10},
  299. {"foo\nbar\r\n\njunk", 10},
  300. };
  301. for (const auto& test : tests) {
  302. size_t input_len = strlen(test.input);
  303. size_t eoh = HttpUtil::LocateEndOfAdditionalHeaders(test.input, input_len);
  304. EXPECT_EQ(test.expected_result, eoh);
  305. }
  306. }
  307. TEST(HttpUtilTest, AssembleRawHeaders) {
  308. // clang-format off
  309. struct {
  310. const char* const input; // with '|' representing '\0'
  311. const char* const expected_result; // with '\0' changed to '|'
  312. } tests[] = {
  313. { "HTTP/1.0 200 OK\r\nFoo: 1\r\nBar: 2\r\n\r\n",
  314. "HTTP/1.0 200 OK|Foo: 1|Bar: 2||" },
  315. { "HTTP/1.0 200 OK\nFoo: 1\nBar: 2\n\n",
  316. "HTTP/1.0 200 OK|Foo: 1|Bar: 2||" },
  317. // Valid line continuation (single SP).
  318. {
  319. "HTTP/1.0 200 OK\n"
  320. "Foo: 1\n"
  321. " continuation\n"
  322. "Bar: 2\n\n",
  323. "HTTP/1.0 200 OK|"
  324. "Foo: 1 continuation|"
  325. "Bar: 2||"
  326. },
  327. // Valid line continuation (single HT).
  328. {
  329. "HTTP/1.0 200 OK\n"
  330. "Foo: 1\n"
  331. "\tcontinuation\n"
  332. "Bar: 2\n\n",
  333. "HTTP/1.0 200 OK|"
  334. "Foo: 1 continuation|"
  335. "Bar: 2||"
  336. },
  337. // Valid line continuation (multiple SP).
  338. {
  339. "HTTP/1.0 200 OK\n"
  340. "Foo: 1\n"
  341. " continuation\n"
  342. "Bar: 2\n\n",
  343. "HTTP/1.0 200 OK|"
  344. "Foo: 1 continuation|"
  345. "Bar: 2||"
  346. },
  347. // Valid line continuation (multiple HT).
  348. {
  349. "HTTP/1.0 200 OK\n"
  350. "Foo: 1\n"
  351. "\t\t\tcontinuation\n"
  352. "Bar: 2\n\n",
  353. "HTTP/1.0 200 OK|"
  354. "Foo: 1 continuation|"
  355. "Bar: 2||"
  356. },
  357. // Valid line continuation (mixed HT, SP).
  358. {
  359. "HTTP/1.0 200 OK\n"
  360. "Foo: 1\n"
  361. " \t \t continuation\n"
  362. "Bar: 2\n\n",
  363. "HTTP/1.0 200 OK|"
  364. "Foo: 1 continuation|"
  365. "Bar: 2||"
  366. },
  367. // Valid multi-line continuation
  368. {
  369. "HTTP/1.0 200 OK\n"
  370. "Foo: 1\n"
  371. " continuation1\n"
  372. "\tcontinuation2\n"
  373. " continuation3\n"
  374. "Bar: 2\n\n",
  375. "HTTP/1.0 200 OK|"
  376. "Foo: 1 continuation1 continuation2 continuation3|"
  377. "Bar: 2||"
  378. },
  379. // Continuation of quoted value.
  380. // This is different from what Firefox does, since it
  381. // will preserve the LWS.
  382. {
  383. "HTTP/1.0 200 OK\n"
  384. "Etag: \"34534-d3\n"
  385. " 134q\"\n"
  386. "Bar: 2\n\n",
  387. "HTTP/1.0 200 OK|"
  388. "Etag: \"34534-d3 134q\"|"
  389. "Bar: 2||"
  390. },
  391. // Valid multi-line continuation, full LWS lines
  392. {
  393. "HTTP/1.0 200 OK\n"
  394. "Foo: 1\n"
  395. " \n"
  396. "\t\t\t\t\n"
  397. "\t continuation\n"
  398. "Bar: 2\n\n",
  399. // One SP per continued line = 3.
  400. "HTTP/1.0 200 OK|"
  401. "Foo: 1 continuation|"
  402. "Bar: 2||"
  403. },
  404. // Valid multi-line continuation, all LWS
  405. {
  406. "HTTP/1.0 200 OK\n"
  407. "Foo: 1\n"
  408. " \n"
  409. "\t\t\t\t\n"
  410. "\t \n"
  411. "Bar: 2\n\n",
  412. // One SP per continued line = 3.
  413. "HTTP/1.0 200 OK|"
  414. "Foo: 1 |"
  415. "Bar: 2||"
  416. },
  417. // Valid line continuation (No value bytes in first line).
  418. {
  419. "HTTP/1.0 200 OK\n"
  420. "Foo:\n"
  421. " value\n"
  422. "Bar: 2\n\n",
  423. "HTTP/1.0 200 OK|"
  424. "Foo: value|"
  425. "Bar: 2||"
  426. },
  427. // Not a line continuation (can't continue status line).
  428. {
  429. "HTTP/1.0 200 OK\n"
  430. " Foo: 1\n"
  431. "Bar: 2\n\n",
  432. "HTTP/1.0 200 OK|"
  433. " Foo: 1|"
  434. "Bar: 2||"
  435. },
  436. // Not a line continuation (can't continue status line).
  437. {
  438. "HTTP/1.0\n"
  439. " 200 OK\n"
  440. "Foo: 1\n"
  441. "Bar: 2\n\n",
  442. "HTTP/1.0|"
  443. " 200 OK|"
  444. "Foo: 1|"
  445. "Bar: 2||"
  446. },
  447. // Not a line continuation (can't continue status line).
  448. {
  449. "HTTP/1.0 404\n"
  450. " Not Found\n"
  451. "Foo: 1\n"
  452. "Bar: 2\n\n",
  453. "HTTP/1.0 404|"
  454. " Not Found|"
  455. "Foo: 1|"
  456. "Bar: 2||"
  457. },
  458. // Unterminated status line.
  459. {
  460. "HTTP/1.0 200 OK",
  461. "HTTP/1.0 200 OK||"
  462. },
  463. // Single terminated, with headers
  464. {
  465. "HTTP/1.0 200 OK\n"
  466. "Foo: 1\n"
  467. "Bar: 2\n",
  468. "HTTP/1.0 200 OK|"
  469. "Foo: 1|"
  470. "Bar: 2||"
  471. },
  472. // Not terminated, with headers
  473. {
  474. "HTTP/1.0 200 OK\n"
  475. "Foo: 1\n"
  476. "Bar: 2",
  477. "HTTP/1.0 200 OK|"
  478. "Foo: 1|"
  479. "Bar: 2||"
  480. },
  481. // Not a line continuation (VT)
  482. {
  483. "HTTP/1.0 200 OK\n"
  484. "Foo: 1\n"
  485. "\vInvalidContinuation\n"
  486. "Bar: 2\n\n",
  487. "HTTP/1.0 200 OK|"
  488. "Foo: 1|"
  489. "\vInvalidContinuation|"
  490. "Bar: 2||"
  491. },
  492. // Not a line continuation (formfeed)
  493. {
  494. "HTTP/1.0 200 OK\n"
  495. "Foo: 1\n"
  496. "\fInvalidContinuation\n"
  497. "Bar: 2\n\n",
  498. "HTTP/1.0 200 OK|"
  499. "Foo: 1|"
  500. "\fInvalidContinuation|"
  501. "Bar: 2||"
  502. },
  503. // Not a line continuation -- can't continue header names.
  504. {
  505. "HTTP/1.0 200 OK\n"
  506. "Serv\n"
  507. " er: Apache\n"
  508. "\tInvalidContinuation\n"
  509. "Bar: 2\n\n",
  510. "HTTP/1.0 200 OK|"
  511. "Serv|"
  512. " er: Apache|"
  513. "\tInvalidContinuation|"
  514. "Bar: 2||"
  515. },
  516. // Not a line continuation -- no value to continue.
  517. {
  518. "HTTP/1.0 200 OK\n"
  519. "Foo: 1\n"
  520. "garbage\n"
  521. " not-a-continuation\n"
  522. "Bar: 2\n\n",
  523. "HTTP/1.0 200 OK|"
  524. "Foo: 1|"
  525. "garbage|"
  526. " not-a-continuation|"
  527. "Bar: 2||",
  528. },
  529. // Not a line continuation -- no valid name.
  530. {
  531. "HTTP/1.0 200 OK\n"
  532. ": 1\n"
  533. " garbage\n"
  534. "Bar: 2\n\n",
  535. "HTTP/1.0 200 OK|"
  536. ": 1|"
  537. " garbage|"
  538. "Bar: 2||",
  539. },
  540. // Not a line continuation -- no valid name (whitespace)
  541. {
  542. "HTTP/1.0 200 OK\n"
  543. " : 1\n"
  544. " garbage\n"
  545. "Bar: 2\n\n",
  546. "HTTP/1.0 200 OK|"
  547. " : 1|"
  548. " garbage|"
  549. "Bar: 2||",
  550. },
  551. // Embed NULLs in the status line. They should not be understood
  552. // as line separators.
  553. {
  554. "HTTP/1.0 200 OK|Bar2:0|Baz2:1\r\nFoo: 1\r\nBar: 2\r\n\r\n",
  555. "HTTP/1.0 200 OKBar2:0Baz2:1|Foo: 1|Bar: 2||"
  556. },
  557. // Embed NULLs in a header line. They should not be understood as
  558. // line separators.
  559. {
  560. "HTTP/1.0 200 OK\nFoo: 1|Foo2: 3\nBar: 2\n\n",
  561. "HTTP/1.0 200 OK|Foo: 1Foo2: 3|Bar: 2||"
  562. },
  563. // The embedded NUL at the start of the line (before "Blah:") should not be
  564. // interpreted as LWS (as that would mistake it for a header line
  565. // continuation).
  566. {
  567. "HTTP/1.0 200 OK\n"
  568. "Foo: 1\n"
  569. "|Blah: 3\n"
  570. "Bar: 2\n\n",
  571. "HTTP/1.0 200 OK|Foo: 1|Blah: 3|Bar: 2||"
  572. },
  573. };
  574. // clang-format on
  575. for (const auto& test : tests) {
  576. std::string input = test.input;
  577. std::replace(input.begin(), input.end(), '|', '\0');
  578. std::string raw = HttpUtil::AssembleRawHeaders(input);
  579. std::replace(raw.begin(), raw.end(), '\0', '|');
  580. EXPECT_EQ(test.expected_result, raw);
  581. }
  582. }
  583. // Test SpecForRequest().
  584. TEST(HttpUtilTest, RequestUrlSanitize) {
  585. struct {
  586. const char* const url;
  587. const char* const expected_spec;
  588. } tests[] = {
  589. { // Check that #hash is removed.
  590. "http://www.google.com:78/foobar?query=1#hash",
  591. "http://www.google.com:78/foobar?query=1",
  592. },
  593. { // The reference may itself contain # -- strip all of it.
  594. "http://192.168.0.1?query=1#hash#10#11#13#14",
  595. "http://192.168.0.1/?query=1",
  596. },
  597. { // Strip username/password.
  598. "http://user:pass@google.com",
  599. "http://google.com/",
  600. },
  601. { // https scheme
  602. "https://www.google.com:78/foobar?query=1#hash",
  603. "https://www.google.com:78/foobar?query=1",
  604. },
  605. { // WebSocket's ws scheme
  606. "ws://www.google.com:78/foobar?query=1#hash",
  607. "ws://www.google.com:78/foobar?query=1",
  608. },
  609. { // WebSocket's wss scheme
  610. "wss://www.google.com:78/foobar?query=1#hash",
  611. "wss://www.google.com:78/foobar?query=1",
  612. }
  613. };
  614. for (size_t i = 0; i < std::size(tests); ++i) {
  615. SCOPED_TRACE(i);
  616. GURL url(GURL(tests[i].url));
  617. std::string expected_spec(tests[i].expected_spec);
  618. EXPECT_EQ(expected_spec, HttpUtil::SpecForRequest(url));
  619. }
  620. }
  621. TEST(HttpUtilTest, GenerateAcceptLanguageHeader) {
  622. std::string header = HttpUtil::GenerateAcceptLanguageHeader("");
  623. EXPECT_TRUE(header.empty());
  624. header = HttpUtil::GenerateAcceptLanguageHeader("es");
  625. EXPECT_EQ(std::string("es"), header);
  626. header = HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de");
  627. EXPECT_EQ(std::string("en-US,fr;q=0.9,de;q=0.8"), header);
  628. header = HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de,ko,zh-CN,ja");
  629. EXPECT_EQ(
  630. std::string("en-US,fr;q=0.9,de;q=0.8,ko;q=0.7,zh-CN;q=0.6,ja;q=0.5"),
  631. header);
  632. }
  633. // HttpResponseHeadersTest.GetMimeType also tests ParseContentType.
  634. TEST(HttpUtilTest, ParseContentType) {
  635. // clang-format off
  636. const struct {
  637. const char* const content_type;
  638. const char* const expected_mime_type;
  639. const char* const expected_charset;
  640. const bool expected_had_charset;
  641. const char* const expected_boundary;
  642. } tests[] = {
  643. { "text/html",
  644. "text/html",
  645. "",
  646. false,
  647. ""
  648. },
  649. { "text/html;",
  650. "text/html",
  651. "",
  652. false,
  653. ""
  654. },
  655. { "text/html; charset=utf-8",
  656. "text/html",
  657. "utf-8",
  658. true,
  659. ""
  660. },
  661. // Parameter name is "charset ", not "charset". See https://crbug.com/772834.
  662. { "text/html; charset =utf-8",
  663. "text/html",
  664. "",
  665. false,
  666. ""
  667. },
  668. { "text/html; charset= utf-8",
  669. "text/html",
  670. "utf-8",
  671. true,
  672. ""
  673. },
  674. { "text/html; charset=utf-8 ",
  675. "text/html",
  676. "utf-8",
  677. true,
  678. ""
  679. },
  680. { "text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs\"",
  681. "text/html",
  682. "",
  683. false,
  684. "WebKit-ada-df-dsf-adsfadsfs"
  685. },
  686. // Parameter name is "boundary ", not "boundary".
  687. // See https://crbug.com/772834.
  688. { "text/html; boundary =\"WebKit-ada-df-dsf-adsfadsfs\"",
  689. "text/html",
  690. "",
  691. false,
  692. ""
  693. },
  694. // Parameter value includes leading space. See https://crbug.com/772834.
  695. { "text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\"",
  696. "text/html",
  697. "",
  698. false,
  699. "WebKit-ada-df-dsf-adsfadsfs"
  700. },
  701. // Parameter value includes leading space. See https://crbug.com/772834.
  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; charset",
  721. "text/html",
  722. "",
  723. false,
  724. ""
  725. },
  726. { "text/html; charset=",
  727. "text/html",
  728. "",
  729. false,
  730. ""
  731. },
  732. { "text/html; charset= ",
  733. "text/html",
  734. "",
  735. false,
  736. ""
  737. },
  738. { "text/html; charset= ;",
  739. "text/html",
  740. "",
  741. false,
  742. ""
  743. },
  744. // Empty quoted strings are allowed.
  745. { "text/html; charset=\"\"",
  746. "text/html",
  747. "",
  748. true,
  749. ""
  750. },
  751. // Leading and trailing whitespace in quotes is trimmed.
  752. { "text/html; charset=\" \"",
  753. "text/html",
  754. "",
  755. true,
  756. ""
  757. },
  758. { "text/html; charset=\" foo \"",
  759. "text/html",
  760. "foo",
  761. true,
  762. ""
  763. },
  764. // With multiple values, should use the first one.
  765. { "text/html; charset=foo; charset=utf-8",
  766. "text/html",
  767. "foo",
  768. true,
  769. ""
  770. },
  771. { "text/html; charset; charset=; charset=utf-8",
  772. "text/html",
  773. "utf-8",
  774. true,
  775. ""
  776. },
  777. { "text/html; charset=utf-8; charset=; charset",
  778. "text/html",
  779. "utf-8",
  780. true,
  781. ""
  782. },
  783. { "text/html; boundary=foo; boundary=bar",
  784. "text/html",
  785. "",
  786. false,
  787. "foo"
  788. },
  789. // Stray quotes ignored.
  790. { "text/html; \"; \"\"; charset=utf-8",
  791. "text/html",
  792. "utf-8",
  793. true,
  794. ""
  795. },
  796. // Non-leading quotes kept as-is.
  797. { "text/html; charset=u\"tf-8\"",
  798. "text/html",
  799. "u\"tf-8\"",
  800. true,
  801. ""
  802. },
  803. { "text/html; charset=\"utf-8\"",
  804. "text/html",
  805. "utf-8",
  806. true,
  807. ""
  808. },
  809. // No closing quote.
  810. { "text/html; charset=\"utf-8",
  811. "text/html",
  812. "utf-8",
  813. true,
  814. ""
  815. },
  816. // Check that \ is treated as an escape character.
  817. { "text/html; charset=\"\\utf\\-\\8\"",
  818. "text/html",
  819. "utf-8",
  820. true,
  821. ""
  822. },
  823. // More interseting escape character test - test escaped backslash, escaped
  824. // quote, and backslash at end of input in unterminated quoted string.
  825. { "text/html; charset=\"\\\\\\\"\\",
  826. "text/html",
  827. "\\\"\\",
  828. true,
  829. ""
  830. },
  831. // Check quoted semicolon.
  832. { "text/html; charset=\";charset=utf-8;\"",
  833. "text/html",
  834. ";charset=utf-8;",
  835. true,
  836. ""
  837. },
  838. // Unclear if this one should just return utf-8 or not.
  839. { "text/html; charset= \"utf-8\"",
  840. "text/html",
  841. "utf-8",
  842. true,
  843. ""
  844. },
  845. // Regression test for https://crbug.com/772350:
  846. // Single quotes are not delimiters but must be treated as part of charset.
  847. { "text/html; charset='utf-8'",
  848. "text/html",
  849. "'utf-8'",
  850. true,
  851. ""
  852. },
  853. // Empty subtype should be accepted.
  854. { "text/",
  855. "text/",
  856. "",
  857. false,
  858. ""
  859. },
  860. // "*/*" is ignored unless it has params, or is not an exact match.
  861. { "*/*", "", "", false, "" },
  862. { "*/*; charset=utf-8", "*/*", "utf-8", true, "" },
  863. { "*/* ", "*/*", "", false, "" },
  864. // Regression test for https://crbug.com/1326529
  865. { "teXT/html", "text/html", "", false, ""},
  866. // TODO(abarth): Add more interesting test cases.
  867. };
  868. // clang-format on
  869. for (const auto& test : tests) {
  870. std::string mime_type;
  871. std::string charset;
  872. bool had_charset = false;
  873. std::string boundary;
  874. HttpUtil::ParseContentType(test.content_type, &mime_type, &charset,
  875. &had_charset, &boundary);
  876. EXPECT_EQ(test.expected_mime_type, mime_type)
  877. << "content_type=" << test.content_type;
  878. EXPECT_EQ(test.expected_charset, charset)
  879. << "content_type=" << test.content_type;
  880. EXPECT_EQ(test.expected_had_charset, had_charset)
  881. << "content_type=" << test.content_type;
  882. EXPECT_EQ(test.expected_boundary, boundary)
  883. << "content_type=" << test.content_type;
  884. }
  885. }
  886. TEST(HttpUtilTest, ParseContentResetCharset) {
  887. std::string mime_type;
  888. std::string charset;
  889. bool had_charset = false;
  890. std::string boundary;
  891. // Set mime (capitalization should be ignored), but not charset.
  892. HttpUtil::ParseContentType("Text/Html", &mime_type, &charset, &had_charset,
  893. &boundary);
  894. EXPECT_EQ("text/html", mime_type);
  895. EXPECT_EQ("", charset);
  896. EXPECT_FALSE(had_charset);
  897. // The same mime, add charset.
  898. HttpUtil::ParseContentType("tExt/hTml;charset=utf-8", &mime_type, &charset,
  899. &had_charset, &boundary);
  900. EXPECT_EQ("text/html", mime_type);
  901. EXPECT_EQ("utf-8", charset);
  902. EXPECT_TRUE(had_charset);
  903. // The same mime (different capitalization), but no charset - should not clear
  904. // charset.
  905. HttpUtil::ParseContentType("teXt/htMl", &mime_type, &charset, &had_charset,
  906. &boundary);
  907. EXPECT_EQ("text/html", mime_type);
  908. EXPECT_EQ("utf-8", charset);
  909. EXPECT_TRUE(had_charset);
  910. // A different mime will clear charset.
  911. HttpUtil::ParseContentType("texT/plaiN", &mime_type, &charset, &had_charset,
  912. &boundary);
  913. EXPECT_EQ("text/plain", mime_type);
  914. EXPECT_EQ("", charset);
  915. EXPECT_TRUE(had_charset);
  916. }
  917. TEST(HttpUtilTest, ParseContentRangeHeader) {
  918. const struct {
  919. const char* const content_range_header_spec;
  920. bool expected_return_value;
  921. int64_t expected_first_byte_position;
  922. int64_t expected_last_byte_position;
  923. int64_t expected_instance_length;
  924. } tests[] = {
  925. {"", false, -1, -1, -1},
  926. {"megabytes 0-10/50", false, -1, -1, -1},
  927. {"0-10/50", false, -1, -1, -1},
  928. {"Bytes 0-50/51", true, 0, 50, 51},
  929. {"bytes 0-50/51", true, 0, 50, 51},
  930. {"bytes\t0-50/51", false, -1, -1, -1},
  931. {" bytes 0-50/51", true, 0, 50, 51},
  932. {" bytes 0 - 50 \t / \t51", true, 0, 50, 51},
  933. {"bytes 0\t-\t50\t/\t51\t", true, 0, 50, 51},
  934. {" \tbytes\t\t\t 0\t-\t50\t/\t51\t", true, 0, 50, 51},
  935. {"\t bytes \t 0 - 50 / 5 1", false, -1, -1, -1},
  936. {"\t bytes \t 0 - 5 0 / 51", false, -1, -1, -1},
  937. {"bytes 50-0/51", false, -1, -1, -1},
  938. {"bytes * /*", false, -1, -1, -1},
  939. {"bytes * / * ", false, -1, -1, -1},
  940. {"bytes 0-50/*", false, -1, -1, -1},
  941. {"bytes 0-50 / * ", false, -1, -1, -1},
  942. {"bytes 0-10000000000/10000000001", true, 0, 10000000000ll,
  943. 10000000001ll},
  944. {"bytes 0-10000000000/10000000000", false, -1, -1, -1},
  945. // 64 bit wraparound.
  946. {"bytes 0 - 9223372036854775807 / 100", false, -1, -1, -1},
  947. // 64 bit wraparound.
  948. {"bytes 0 - 100 / -9223372036854775808", false, -1, -1, -1},
  949. {"bytes */50", false, -1, -1, -1},
  950. {"bytes 0-50/10", false, -1, -1, -1},
  951. {"bytes 40-50/45", false, -1, -1, -1},
  952. {"bytes 0-50/-10", false, -1, -1, -1},
  953. {"bytes 0-0/1", true, 0, 0, 1},
  954. {"bytes 0-40000000000000000000/40000000000000000001", false, -1, -1, -1},
  955. {"bytes 1-/100", false, -1, -1, -1},
  956. {"bytes -/100", false, -1, -1, -1},
  957. {"bytes -1/100", false, -1, -1, -1},
  958. {"bytes 0-1233/*", false, -1, -1, -1},
  959. {"bytes -123 - -1/100", false, -1, -1, -1},
  960. };
  961. for (const auto& test : tests) {
  962. int64_t first_byte_position, last_byte_position, instance_length;
  963. EXPECT_EQ(test.expected_return_value,
  964. HttpUtil::ParseContentRangeHeaderFor206(
  965. test.content_range_header_spec, &first_byte_position,
  966. &last_byte_position, &instance_length))
  967. << test.content_range_header_spec;
  968. EXPECT_EQ(test.expected_first_byte_position, first_byte_position)
  969. << test.content_range_header_spec;
  970. EXPECT_EQ(test.expected_last_byte_position, last_byte_position)
  971. << test.content_range_header_spec;
  972. EXPECT_EQ(test.expected_instance_length, instance_length)
  973. << test.content_range_header_spec;
  974. }
  975. }
  976. TEST(HttpUtilTest, ParseRetryAfterHeader) {
  977. base::Time::Exploded now_exploded = {2014, 11, 4, 5, 22, 39, 30, 0};
  978. base::Time now;
  979. EXPECT_TRUE(base::Time::FromUTCExploded(now_exploded, &now));
  980. base::Time::Exploded later_exploded = {2015, 1, 5, 1, 12, 34, 56, 0};
  981. base::Time later;
  982. EXPECT_TRUE(base::Time::FromUTCExploded(later_exploded, &later));
  983. const struct {
  984. const char* retry_after_string;
  985. bool expected_return_value;
  986. base::TimeDelta expected_retry_after;
  987. } tests[] = {{"", false, base::TimeDelta()},
  988. {"-3", false, base::TimeDelta()},
  989. {"-2", false, base::TimeDelta()},
  990. {"-1", false, base::TimeDelta()},
  991. {"+0", false, base::TimeDelta()},
  992. {"+1", false, base::TimeDelta()},
  993. {"0", true, base::Seconds(0)},
  994. {"1", true, base::Seconds(1)},
  995. {"2", true, base::Seconds(2)},
  996. {"3", true, base::Seconds(3)},
  997. {"60", true, base::Seconds(60)},
  998. {"3600", true, base::Seconds(3600)},
  999. {"86400", true, base::Seconds(86400)},
  1000. {"Thu, 1 Jan 2015 12:34:56 GMT", true, later - now},
  1001. {"Mon, 1 Jan 1900 12:34:56 GMT", false, base::TimeDelta()}};
  1002. for (size_t i = 0; i < std::size(tests); ++i) {
  1003. base::TimeDelta retry_after;
  1004. bool return_value = HttpUtil::ParseRetryAfterHeader(
  1005. tests[i].retry_after_string, now, &retry_after);
  1006. EXPECT_EQ(tests[i].expected_return_value, return_value)
  1007. << "Test case " << i << ": expected " << tests[i].expected_return_value
  1008. << " but got " << return_value << ".";
  1009. if (tests[i].expected_return_value && return_value) {
  1010. EXPECT_EQ(tests[i].expected_retry_after, retry_after)
  1011. << "Test case " << i << ": expected "
  1012. << tests[i].expected_retry_after.InSeconds() << "s but got "
  1013. << retry_after.InSeconds() << "s.";
  1014. }
  1015. }
  1016. }
  1017. namespace {
  1018. void CheckCurrentNameValuePair(HttpUtil::NameValuePairsIterator* parser,
  1019. bool expect_valid,
  1020. std::string expected_name,
  1021. std::string expected_value) {
  1022. ASSERT_EQ(expect_valid, parser->valid());
  1023. if (!expect_valid) {
  1024. return;
  1025. }
  1026. // Let's make sure that these never change (i.e., when a quoted value is
  1027. // unquoted, it should be cached on the first calls and not regenerated
  1028. // later).
  1029. std::string::const_iterator first_value_begin = parser->value_begin();
  1030. std::string::const_iterator first_value_end = parser->value_end();
  1031. ASSERT_EQ(expected_name, std::string(parser->name_begin(),
  1032. parser->name_end()));
  1033. ASSERT_EQ(expected_name, parser->name());
  1034. ASSERT_EQ(expected_value, std::string(parser->value_begin(),
  1035. parser->value_end()));
  1036. ASSERT_EQ(expected_value, parser->value());
  1037. // Make sure they didn't/don't change.
  1038. ASSERT_TRUE(first_value_begin == parser->value_begin());
  1039. ASSERT_TRUE(first_value_end == parser->value_end());
  1040. }
  1041. void CheckNextNameValuePair(HttpUtil::NameValuePairsIterator* parser,
  1042. bool expect_next,
  1043. bool expect_valid,
  1044. std::string expected_name,
  1045. std::string expected_value) {
  1046. ASSERT_EQ(expect_next, parser->GetNext());
  1047. ASSERT_EQ(expect_valid, parser->valid());
  1048. if (!expect_next || !expect_valid) {
  1049. return;
  1050. }
  1051. CheckCurrentNameValuePair(parser,
  1052. expect_valid,
  1053. expected_name,
  1054. expected_value);
  1055. }
  1056. void CheckInvalidNameValuePair(std::string valid_part,
  1057. std::string invalid_part) {
  1058. std::string whole_string = valid_part + invalid_part;
  1059. HttpUtil::NameValuePairsIterator valid_parser(valid_part.begin(),
  1060. valid_part.end(),
  1061. ';');
  1062. HttpUtil::NameValuePairsIterator invalid_parser(whole_string.begin(),
  1063. whole_string.end(),
  1064. ';');
  1065. ASSERT_TRUE(valid_parser.valid());
  1066. ASSERT_TRUE(invalid_parser.valid());
  1067. // Both parsers should return all the same values until "valid_parser" is
  1068. // exhausted.
  1069. while (valid_parser.GetNext()) {
  1070. ASSERT_TRUE(invalid_parser.GetNext());
  1071. ASSERT_TRUE(valid_parser.valid());
  1072. ASSERT_TRUE(invalid_parser.valid());
  1073. ASSERT_EQ(valid_parser.name(), invalid_parser.name());
  1074. ASSERT_EQ(valid_parser.value(), invalid_parser.value());
  1075. }
  1076. // valid_parser is exhausted and remains 'valid'
  1077. ASSERT_TRUE(valid_parser.valid());
  1078. // invalid_parser's corresponding call to GetNext also returns false...
  1079. ASSERT_FALSE(invalid_parser.GetNext());
  1080. // ...but the parser is in an invalid state.
  1081. ASSERT_FALSE(invalid_parser.valid());
  1082. }
  1083. } // namespace
  1084. TEST(HttpUtilTest, NameValuePairsIteratorCopyAndAssign) {
  1085. std::string data =
  1086. "alpha=\"\\\"a\\\"\"; beta=\" b \"; cappa=\"c;\"; delta=\"d\"";
  1087. HttpUtil::NameValuePairsIterator parser_a(data.begin(), data.end(), ';');
  1088. EXPECT_TRUE(parser_a.valid());
  1089. ASSERT_NO_FATAL_FAILURE(
  1090. CheckNextNameValuePair(&parser_a, true, true, "alpha", "\"a\""));
  1091. HttpUtil::NameValuePairsIterator parser_b(parser_a);
  1092. // a and b now point to same location
  1093. ASSERT_NO_FATAL_FAILURE(
  1094. CheckCurrentNameValuePair(&parser_b, true, "alpha", "\"a\""));
  1095. ASSERT_NO_FATAL_FAILURE(
  1096. CheckCurrentNameValuePair(&parser_a, true, "alpha", "\"a\""));
  1097. // advance a, no effect on b
  1098. ASSERT_NO_FATAL_FAILURE(
  1099. CheckNextNameValuePair(&parser_a, true, true, "beta", " b "));
  1100. ASSERT_NO_FATAL_FAILURE(
  1101. CheckCurrentNameValuePair(&parser_b, true, "alpha", "\"a\""));
  1102. // assign b the current state of a, no effect on a
  1103. parser_b = parser_a;
  1104. ASSERT_NO_FATAL_FAILURE(
  1105. CheckCurrentNameValuePair(&parser_b, true, "beta", " b "));
  1106. ASSERT_NO_FATAL_FAILURE(
  1107. CheckCurrentNameValuePair(&parser_a, true, "beta", " b "));
  1108. // advance b, no effect on a
  1109. ASSERT_NO_FATAL_FAILURE(
  1110. CheckNextNameValuePair(&parser_b, true, true, "cappa", "c;"));
  1111. ASSERT_NO_FATAL_FAILURE(
  1112. CheckCurrentNameValuePair(&parser_a, true, "beta", " b "));
  1113. }
  1114. TEST(HttpUtilTest, NameValuePairsIteratorEmptyInput) {
  1115. std::string data;
  1116. HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
  1117. EXPECT_TRUE(parser.valid());
  1118. ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
  1119. &parser, false, true, std::string(), std::string()));
  1120. }
  1121. TEST(HttpUtilTest, NameValuePairsIterator) {
  1122. std::string data =
  1123. "alpha=1; beta= 2 ;"
  1124. "cappa =' 3; foo=';"
  1125. "cappa =\" 3; foo=\";"
  1126. "delta= \" \\\"4\\\" \"; e= \" '5'\"; e=6;"
  1127. "f=\"\\\"\\h\\e\\l\\l\\o\\ \\w\\o\\r\\l\\d\\\"\";"
  1128. "g=\"\"; h=\"hello\"";
  1129. HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
  1130. EXPECT_TRUE(parser.valid());
  1131. ASSERT_NO_FATAL_FAILURE(
  1132. CheckNextNameValuePair(&parser, true, true, "alpha", "1"));
  1133. ASSERT_NO_FATAL_FAILURE(
  1134. CheckNextNameValuePair(&parser, true, true, "beta", "2"));
  1135. // Single quotes shouldn't be treated as quotes.
  1136. ASSERT_NO_FATAL_FAILURE(
  1137. CheckNextNameValuePair(&parser, true, true, "cappa", "' 3"));
  1138. ASSERT_NO_FATAL_FAILURE(
  1139. CheckNextNameValuePair(&parser, true, true, "foo", "'"));
  1140. // But double quotes should be, and can contain semi-colons and equal signs.
  1141. ASSERT_NO_FATAL_FAILURE(
  1142. CheckNextNameValuePair(&parser, true, true, "cappa", " 3; foo="));
  1143. ASSERT_NO_FATAL_FAILURE(
  1144. CheckNextNameValuePair(&parser, true, true, "delta", " \"4\" "));
  1145. ASSERT_NO_FATAL_FAILURE(
  1146. CheckNextNameValuePair(&parser, true, true, "e", " '5'"));
  1147. ASSERT_NO_FATAL_FAILURE(
  1148. CheckNextNameValuePair(&parser, true, true, "e", "6"));
  1149. ASSERT_NO_FATAL_FAILURE(
  1150. CheckNextNameValuePair(&parser, true, true, "f", "\"hello world\""));
  1151. ASSERT_NO_FATAL_FAILURE(
  1152. CheckNextNameValuePair(&parser, true, true, "g", std::string()));
  1153. ASSERT_NO_FATAL_FAILURE(
  1154. CheckNextNameValuePair(&parser, true, true, "h", "hello"));
  1155. ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
  1156. &parser, false, true, std::string(), std::string()));
  1157. }
  1158. TEST(HttpUtilTest, NameValuePairsIteratorOptionalValues) {
  1159. std::string data = "alpha=1; beta;cappa ; delta; e ; f=1";
  1160. // Test that the default parser requires values.
  1161. HttpUtil::NameValuePairsIterator default_parser(data.begin(), data.end(),
  1162. ';');
  1163. EXPECT_TRUE(default_parser.valid());
  1164. ASSERT_NO_FATAL_FAILURE(
  1165. CheckNextNameValuePair(&default_parser, true, true, "alpha", "1"));
  1166. ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&default_parser, false, false,
  1167. std::string(), std::string()));
  1168. HttpUtil::NameValuePairsIterator values_required_parser(
  1169. data.begin(), data.end(), ';',
  1170. HttpUtil::NameValuePairsIterator::Values::REQUIRED,
  1171. HttpUtil::NameValuePairsIterator::Quotes::NOT_STRICT);
  1172. EXPECT_TRUE(values_required_parser.valid());
  1173. ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&values_required_parser, true,
  1174. true, "alpha", "1"));
  1175. ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
  1176. &values_required_parser, false, false, std::string(), std::string()));
  1177. HttpUtil::NameValuePairsIterator parser(
  1178. data.begin(), data.end(), ';',
  1179. HttpUtil::NameValuePairsIterator::Values::NOT_REQUIRED,
  1180. HttpUtil::NameValuePairsIterator::Quotes::NOT_STRICT);
  1181. EXPECT_TRUE(parser.valid());
  1182. ASSERT_NO_FATAL_FAILURE(
  1183. CheckNextNameValuePair(&parser, true, true, "alpha", "1"));
  1184. ASSERT_NO_FATAL_FAILURE(
  1185. CheckNextNameValuePair(&parser, true, true, "beta", std::string()));
  1186. ASSERT_NO_FATAL_FAILURE(
  1187. CheckNextNameValuePair(&parser, true, true, "cappa", std::string()));
  1188. ASSERT_NO_FATAL_FAILURE(
  1189. CheckNextNameValuePair(&parser, true, true, "delta", std::string()));
  1190. ASSERT_NO_FATAL_FAILURE(
  1191. CheckNextNameValuePair(&parser, true, true, "e", std::string()));
  1192. ASSERT_NO_FATAL_FAILURE(
  1193. CheckNextNameValuePair(&parser, true, true, "f", "1"));
  1194. ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&parser, false, true,
  1195. std::string(), std::string()));
  1196. EXPECT_TRUE(parser.valid());
  1197. }
  1198. TEST(HttpUtilTest, NameValuePairsIteratorIllegalInputs) {
  1199. ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; beta"));
  1200. ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "beta"));
  1201. ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; \"beta\"=2"));
  1202. ASSERT_NO_FATAL_FAILURE(
  1203. CheckInvalidNameValuePair(std::string(), "\"beta\"=2"));
  1204. ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";beta="));
  1205. ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1",
  1206. ";beta=;cappa=2"));
  1207. // According to the spec this is an error, but it doesn't seem appropriate to
  1208. // change our behaviour to be less permissive at this time.
  1209. // See NameValuePairsIteratorExtraSeparators test
  1210. // ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";; beta=2"));
  1211. }
  1212. // If we are going to support extra separators against the spec, let's just make
  1213. // sure they work rationally.
  1214. TEST(HttpUtilTest, NameValuePairsIteratorExtraSeparators) {
  1215. std::string data = " ; ;;alpha=1; ;; ; beta= 2;cappa=3;;; ; ";
  1216. HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
  1217. EXPECT_TRUE(parser.valid());
  1218. ASSERT_NO_FATAL_FAILURE(
  1219. CheckNextNameValuePair(&parser, true, true, "alpha", "1"));
  1220. ASSERT_NO_FATAL_FAILURE(
  1221. CheckNextNameValuePair(&parser, true, true, "beta", "2"));
  1222. ASSERT_NO_FATAL_FAILURE(
  1223. CheckNextNameValuePair(&parser, true, true, "cappa", "3"));
  1224. ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
  1225. &parser, false, true, std::string(), std::string()));
  1226. }
  1227. // See comments on the implementation of NameValuePairsIterator::GetNext
  1228. // regarding this derogation from the spec.
  1229. TEST(HttpUtilTest, NameValuePairsIteratorMissingEndQuote) {
  1230. std::string data = "name=\"value";
  1231. HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
  1232. EXPECT_TRUE(parser.valid());
  1233. ASSERT_NO_FATAL_FAILURE(
  1234. CheckNextNameValuePair(&parser, true, true, "name", "value"));
  1235. ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
  1236. &parser, false, true, std::string(), std::string()));
  1237. }
  1238. TEST(HttpUtilTest, NameValuePairsIteratorStrictQuotesEscapedEndQuote) {
  1239. std::string data = "foo=bar; name=\"value\\\"";
  1240. HttpUtil::NameValuePairsIterator parser(
  1241. data.begin(), data.end(), ';',
  1242. HttpUtil::NameValuePairsIterator::Values::REQUIRED,
  1243. HttpUtil::NameValuePairsIterator::Quotes::STRICT_QUOTES);
  1244. EXPECT_TRUE(parser.valid());
  1245. ASSERT_NO_FATAL_FAILURE(
  1246. CheckNextNameValuePair(&parser, true, true, "foo", "bar"));
  1247. ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&parser, false, false,
  1248. std::string(), std::string()));
  1249. }
  1250. TEST(HttpUtilTest, NameValuePairsIteratorStrictQuotesQuoteInValue) {
  1251. std::string data = "foo=\"bar\"; name=\"va\"lue\"";
  1252. HttpUtil::NameValuePairsIterator parser(
  1253. data.begin(), data.end(), ';',
  1254. HttpUtil::NameValuePairsIterator::Values::REQUIRED,
  1255. HttpUtil::NameValuePairsIterator::Quotes::STRICT_QUOTES);
  1256. EXPECT_TRUE(parser.valid());
  1257. ASSERT_NO_FATAL_FAILURE(
  1258. CheckNextNameValuePair(&parser, true, true, "foo", "bar"));
  1259. ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&parser, false, false,
  1260. std::string(), std::string()));
  1261. }
  1262. TEST(HttpUtilTest, NameValuePairsIteratorStrictQuotesMissingEndQuote) {
  1263. std::string data = "foo=\"bar\"; name=\"value";
  1264. HttpUtil::NameValuePairsIterator parser(
  1265. data.begin(), data.end(), ';',
  1266. HttpUtil::NameValuePairsIterator::Values::REQUIRED,
  1267. HttpUtil::NameValuePairsIterator::Quotes::STRICT_QUOTES);
  1268. EXPECT_TRUE(parser.valid());
  1269. ASSERT_NO_FATAL_FAILURE(
  1270. CheckNextNameValuePair(&parser, true, true, "foo", "bar"));
  1271. ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&parser, false, false,
  1272. std::string(), std::string()));
  1273. }
  1274. TEST(HttpUtilTest, NameValuePairsIteratorStrictQuotesSingleQuotes) {
  1275. std::string data = "foo=\"bar\"; name='value; ok=it'";
  1276. HttpUtil::NameValuePairsIterator parser(
  1277. data.begin(), data.end(), ';',
  1278. HttpUtil::NameValuePairsIterator::Values::REQUIRED,
  1279. HttpUtil::NameValuePairsIterator::Quotes::STRICT_QUOTES);
  1280. EXPECT_TRUE(parser.valid());
  1281. ASSERT_NO_FATAL_FAILURE(
  1282. CheckNextNameValuePair(&parser, true, true, "foo", "bar"));
  1283. ASSERT_NO_FATAL_FAILURE(
  1284. CheckNextNameValuePair(&parser, true, true, "name", "'value"));
  1285. ASSERT_NO_FATAL_FAILURE(
  1286. CheckNextNameValuePair(&parser, true, true, "ok", "it'"));
  1287. }
  1288. TEST(HttpUtilTest, HasValidators) {
  1289. const char* const kMissing = "";
  1290. const char* const kEtagEmpty = "\"\"";
  1291. const char* const kEtagStrong = "\"strong\"";
  1292. const char* const kEtagWeak = "W/\"weak\"";
  1293. const char* const kLastModified = "Tue, 15 Nov 1994 12:45:26 GMT";
  1294. const char* const kLastModifiedInvalid = "invalid";
  1295. const HttpVersion v0_9 = HttpVersion(0, 9);
  1296. EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kMissing, kMissing));
  1297. EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagStrong, kMissing));
  1298. EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagWeak, kMissing));
  1299. EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagEmpty, kMissing));
  1300. EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kMissing, kLastModified));
  1301. EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagStrong, kLastModified));
  1302. EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagWeak, kLastModified));
  1303. EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagEmpty, kLastModified));
  1304. EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kMissing, kLastModifiedInvalid));
  1305. EXPECT_FALSE(
  1306. HttpUtil::HasValidators(v0_9, kEtagStrong, kLastModifiedInvalid));
  1307. EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagWeak, kLastModifiedInvalid));
  1308. EXPECT_FALSE(HttpUtil::HasValidators(v0_9, kEtagEmpty, kLastModifiedInvalid));
  1309. const HttpVersion v1_0 = HttpVersion(1, 0);
  1310. EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kMissing, kMissing));
  1311. EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagStrong, kMissing));
  1312. EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagWeak, kMissing));
  1313. EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagEmpty, kMissing));
  1314. EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kMissing, kLastModified));
  1315. EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kEtagStrong, kLastModified));
  1316. EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kEtagWeak, kLastModified));
  1317. EXPECT_TRUE(HttpUtil::HasValidators(v1_0, kEtagEmpty, kLastModified));
  1318. EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kMissing, kLastModifiedInvalid));
  1319. EXPECT_FALSE(
  1320. HttpUtil::HasValidators(v1_0, kEtagStrong, kLastModifiedInvalid));
  1321. EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagWeak, kLastModifiedInvalid));
  1322. EXPECT_FALSE(HttpUtil::HasValidators(v1_0, kEtagEmpty, kLastModifiedInvalid));
  1323. const HttpVersion v1_1 = HttpVersion(1, 1);
  1324. EXPECT_FALSE(HttpUtil::HasValidators(v1_1, kMissing, kMissing));
  1325. EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagStrong, kMissing));
  1326. EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagWeak, kMissing));
  1327. EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kMissing));
  1328. EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kMissing, kLastModified));
  1329. EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagStrong, kLastModified));
  1330. EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagWeak, kLastModified));
  1331. EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kLastModified));
  1332. EXPECT_FALSE(HttpUtil::HasValidators(v1_1, kMissing, kLastModifiedInvalid));
  1333. EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagStrong, kLastModifiedInvalid));
  1334. EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagWeak, kLastModifiedInvalid));
  1335. EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kLastModifiedInvalid));
  1336. }
  1337. TEST(HttpUtilTest, IsValidHeaderValue) {
  1338. const char* const invalid_values[] = {
  1339. "X-Requested-With: chrome${NUL}Sec-Unsafe: injected",
  1340. "X-Requested-With: chrome\r\nSec-Unsafe: injected",
  1341. "X-Requested-With: chrome\nSec-Unsafe: injected",
  1342. "X-Requested-With: chrome\rSec-Unsafe: injected",
  1343. };
  1344. for (const std::string& value : invalid_values) {
  1345. std::string replaced = value;
  1346. base::ReplaceSubstringsAfterOffset(&replaced, 0, "${NUL}",
  1347. std::string(1, '\0'));
  1348. EXPECT_FALSE(HttpUtil::IsValidHeaderValue(replaced)) << replaced;
  1349. }
  1350. // Check that all characters permitted by RFC7230 3.2.6 are allowed.
  1351. std::string allowed = "\t";
  1352. for (char c = '\x20'; c < '\x7F'; ++c) {
  1353. allowed.append(1, c);
  1354. }
  1355. for (int c = 0x80; c <= 0xFF; ++c) {
  1356. allowed.append(1, static_cast<char>(c));
  1357. }
  1358. EXPECT_TRUE(HttpUtil::IsValidHeaderValue(allowed));
  1359. }
  1360. TEST(HttpUtilTest, IsToken) {
  1361. EXPECT_TRUE(HttpUtil::IsToken("valid"));
  1362. EXPECT_TRUE(HttpUtil::IsToken("!"));
  1363. EXPECT_TRUE(HttpUtil::IsToken("~"));
  1364. EXPECT_FALSE(HttpUtil::IsToken(""));
  1365. EXPECT_FALSE(HttpUtil::IsToken(base::StringPiece()));
  1366. EXPECT_FALSE(HttpUtil::IsToken("hello, world"));
  1367. EXPECT_FALSE(HttpUtil::IsToken(" "));
  1368. EXPECT_FALSE(HttpUtil::IsToken(base::StringPiece("\0", 1)));
  1369. EXPECT_FALSE(HttpUtil::IsToken("\x01"));
  1370. EXPECT_FALSE(HttpUtil::IsToken("\x7F"));
  1371. EXPECT_FALSE(HttpUtil::IsToken("\x80"));
  1372. EXPECT_FALSE(HttpUtil::IsToken("\xff"));
  1373. }
  1374. TEST(HttpUtilTest, IsLWS) {
  1375. EXPECT_FALSE(HttpUtil::IsLWS('\v'));
  1376. EXPECT_FALSE(HttpUtil::IsLWS('\0'));
  1377. EXPECT_FALSE(HttpUtil::IsLWS('1'));
  1378. EXPECT_FALSE(HttpUtil::IsLWS('a'));
  1379. EXPECT_FALSE(HttpUtil::IsLWS('.'));
  1380. EXPECT_FALSE(HttpUtil::IsLWS('\n'));
  1381. EXPECT_FALSE(HttpUtil::IsLWS('\r'));
  1382. EXPECT_TRUE(HttpUtil::IsLWS('\t'));
  1383. EXPECT_TRUE(HttpUtil::IsLWS(' '));
  1384. }
  1385. TEST(HttpUtilTest, IsControlChar) {
  1386. EXPECT_FALSE(HttpUtil::IsControlChar('1'));
  1387. EXPECT_FALSE(HttpUtil::IsControlChar('a'));
  1388. EXPECT_FALSE(HttpUtil::IsControlChar('.'));
  1389. EXPECT_FALSE(HttpUtil::IsControlChar('$'));
  1390. EXPECT_FALSE(HttpUtil::IsControlChar('\x7E'));
  1391. EXPECT_FALSE(HttpUtil::IsControlChar('\x80'));
  1392. EXPECT_FALSE(HttpUtil::IsControlChar('\xFF'));
  1393. EXPECT_TRUE(HttpUtil::IsControlChar('\0'));
  1394. EXPECT_TRUE(HttpUtil::IsControlChar('\v'));
  1395. EXPECT_TRUE(HttpUtil::IsControlChar('\n'));
  1396. EXPECT_TRUE(HttpUtil::IsControlChar('\r'));
  1397. EXPECT_TRUE(HttpUtil::IsControlChar('\t'));
  1398. EXPECT_TRUE(HttpUtil::IsControlChar('\x01'));
  1399. EXPECT_TRUE(HttpUtil::IsControlChar('\x7F'));
  1400. }
  1401. TEST(HttpUtilTest, ParseAcceptEncoding) {
  1402. const struct {
  1403. const char* const value;
  1404. const char* const expected;
  1405. } tests[] = {
  1406. {"", "*"},
  1407. {"identity;q=1, *;q=0", "identity"},
  1408. {"identity", "identity"},
  1409. {"FOO, Bar", "bar|foo|identity"},
  1410. {"foo; q=1", "foo|identity"},
  1411. {"abc, foo; Q=1.0", "abc|foo|identity"},
  1412. {"abc, foo;q= 1.00 , bar", "abc|bar|foo|identity"},
  1413. {"abc, foo; q=1.000, bar", "abc|bar|foo|identity"},
  1414. {"abc, foo ; q = 0 , bar", "abc|bar|identity"},
  1415. {"abc, foo; q=0.0, bar", "abc|bar|identity"},
  1416. {"abc, foo; q=0.00, bar", "abc|bar|identity"},
  1417. {"abc, foo; q=0.000, bar", "abc|bar|identity"},
  1418. {"abc, foo; q=0.001, bar", "abc|bar|foo|identity"},
  1419. {"gzip", "gzip|identity|x-gzip"},
  1420. {"x-gzip", "gzip|identity|x-gzip"},
  1421. {"compress", "compress|identity|x-compress"},
  1422. {"x-compress", "compress|identity|x-compress"},
  1423. {"x-compress", "compress|identity|x-compress"},
  1424. {"foo bar", "INVALID"},
  1425. {"foo;", "INVALID"},
  1426. {"foo;w=1", "INVALID"},
  1427. {"foo;q+1", "INVALID"},
  1428. {"foo;q=2", "INVALID"},
  1429. {"foo;q=1.001", "INVALID"},
  1430. {"foo;q=0.", "INVALID"},
  1431. {"foo,\"bar\"", "INVALID"},
  1432. };
  1433. for (const auto& test : tests) {
  1434. std::string value(test.value);
  1435. std::string reformatted;
  1436. std::set<std::string> allowed_encodings;
  1437. if (!HttpUtil::ParseAcceptEncoding(value, &allowed_encodings)) {
  1438. reformatted = "INVALID";
  1439. } else {
  1440. std::vector<std::string> encodings_list;
  1441. for (auto const& encoding : allowed_encodings)
  1442. encodings_list.push_back(encoding);
  1443. reformatted = base::JoinString(encodings_list, "|");
  1444. }
  1445. EXPECT_STREQ(test.expected, reformatted.c_str())
  1446. << "value=\"" << value << "\"";
  1447. }
  1448. }
  1449. TEST(HttpUtilTest, ParseContentEncoding) {
  1450. const struct {
  1451. const char* const value;
  1452. const char* const expected;
  1453. } tests[] = {
  1454. {"", ""},
  1455. {"identity;q=1, *;q=0", "INVALID"},
  1456. {"identity", "identity"},
  1457. {"FOO, zergli , Bar", "bar|foo|zergli"},
  1458. {"foo, *", "INVALID"},
  1459. {"foo,\"bar\"", "INVALID"},
  1460. };
  1461. for (const auto& test : tests) {
  1462. std::string value(test.value);
  1463. std::string reformatted;
  1464. std::set<std::string> used_encodings;
  1465. if (!HttpUtil::ParseContentEncoding(value, &used_encodings)) {
  1466. reformatted = "INVALID";
  1467. } else {
  1468. std::vector<std::string> encodings_list;
  1469. for (auto const& encoding : used_encodings)
  1470. encodings_list.push_back(encoding);
  1471. reformatted = base::JoinString(encodings_list, "|");
  1472. }
  1473. EXPECT_STREQ(test.expected, reformatted.c_str())
  1474. << "value=\"" << value << "\"";
  1475. }
  1476. }
  1477. // Test the expansion of the Language List.
  1478. TEST(HttpUtilTest, ExpandLanguageList) {
  1479. EXPECT_EQ("", HttpUtil::ExpandLanguageList(""));
  1480. EXPECT_EQ("en-US,en", HttpUtil::ExpandLanguageList("en-US"));
  1481. EXPECT_EQ("fr", HttpUtil::ExpandLanguageList("fr"));
  1482. // The base language is added after all regional codes...
  1483. EXPECT_EQ("en-US,en-CA,en", HttpUtil::ExpandLanguageList("en-US,en-CA"));
  1484. // ... but before other language families.
  1485. EXPECT_EQ("en-US,en-CA,en,fr",
  1486. HttpUtil::ExpandLanguageList("en-US,en-CA,fr"));
  1487. EXPECT_EQ("en-US,en-CA,en,fr,en-AU",
  1488. HttpUtil::ExpandLanguageList("en-US,en-CA,fr,en-AU"));
  1489. EXPECT_EQ("en-US,en-CA,en,fr-CA,fr",
  1490. HttpUtil::ExpandLanguageList("en-US,en-CA,fr-CA"));
  1491. // Add a base language even if it's already in the list.
  1492. EXPECT_EQ("en-US,en,fr-CA,fr,it,es-AR,es,it-IT",
  1493. HttpUtil::ExpandLanguageList("en-US,fr-CA,it,fr,es-AR,it-IT"));
  1494. // Trims a whitespace.
  1495. EXPECT_EQ("en-US,en,fr", HttpUtil::ExpandLanguageList("en-US, fr"));
  1496. // Do not expand the single character subtag 'x' as a language.
  1497. EXPECT_EQ("x-private-agreement-subtags",
  1498. HttpUtil::ExpandLanguageList("x-private-agreement-subtags"));
  1499. // Do not expand the single character subtag 'i' as a language.
  1500. EXPECT_EQ("i-klingon", HttpUtil::ExpandLanguageList("i-klingon"));
  1501. }
  1502. } // namespace net