1/* 2 * nghttp2 - HTTP/2 C Library 3 * 4 * Copyright (c) 2013 Tatsuhiro Tsujikawa 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25#include "http2_test.h" 26 27#include <cassert> 28#include <cstring> 29#include <iostream> 30 31#include <CUnit/CUnit.h> 32 33#include "url-parser/url_parser.h" 34 35#include "http2.h" 36#include "util.h" 37 38using namespace nghttp2; 39 40#define MAKE_NV(K, V) \ 41 { \ 42 (uint8_t *)K, (uint8_t *)V, sizeof(K) - 1, sizeof(V) - 1, \ 43 NGHTTP2_NV_FLAG_NONE \ 44 } 45 46namespace shrpx { 47 48namespace { 49void check_nv(const HeaderRef &a, const nghttp2_nv *b) { 50 CU_ASSERT(a.name.size() == b->namelen); 51 CU_ASSERT(a.value.size() == b->valuelen); 52 CU_ASSERT(memcmp(a.name.c_str(), b->name, b->namelen) == 0); 53 CU_ASSERT(memcmp(a.value.c_str(), b->value, b->valuelen) == 0); 54} 55} // namespace 56 57void test_http2_add_header(void) { 58 auto nva = Headers(); 59 60 http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"123", 3, 61 false, -1); 62 CU_ASSERT(Headers::value_type("alpha", "123") == nva[0]); 63 CU_ASSERT(!nva[0].no_index); 64 65 nva.clear(); 66 67 http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"", 0, 68 true, -1); 69 CU_ASSERT(Headers::value_type("alpha", "") == nva[0]); 70 CU_ASSERT(nva[0].no_index); 71 72 nva.clear(); 73 74 http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" b", 2, 75 false, -1); 76 CU_ASSERT(Headers::value_type("a", "b") == nva[0]); 77 78 nva.clear(); 79 80 http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)"b ", 2, 81 false, -1); 82 CU_ASSERT(Headers::value_type("a", "b") == nva[0]); 83 84 nva.clear(); 85 86 http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" b ", 5, 87 false, -1); 88 CU_ASSERT(Headers::value_type("a", "b") == nva[0]); 89 90 nva.clear(); 91 92 http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" bravo ", 93 9, false, -1); 94 CU_ASSERT(Headers::value_type("a", "bravo") == nva[0]); 95 96 nva.clear(); 97 98 http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" ", 4, 99 false, -1); 100 CU_ASSERT(Headers::value_type("a", "") == nva[0]); 101 102 nva.clear(); 103 104 http2::add_header(nva, (const uint8_t *)"te", 2, (const uint8_t *)"trailers", 105 8, false, http2::HD_TE); 106 CU_ASSERT(http2::HD_TE == nva[0].token); 107} 108 109void test_http2_get_header(void) { 110 auto nva = Headers{{"alpha", "1"}, {"bravo", "2"}, {"bravo", "3"}, 111 {"charlie", "4"}, {"delta", "5"}, {"echo", "6"}, 112 {"content-length", "7"}}; 113 const Headers::value_type *rv; 114 rv = http2::get_header(nva, "delta"); 115 CU_ASSERT(rv != nullptr); 116 CU_ASSERT("delta" == rv->name); 117 118 rv = http2::get_header(nva, "bravo"); 119 CU_ASSERT(rv != nullptr); 120 CU_ASSERT("bravo" == rv->name); 121 122 rv = http2::get_header(nva, "foxtrot"); 123 CU_ASSERT(rv == nullptr); 124 125 http2::HeaderIndex hdidx; 126 http2::init_hdidx(hdidx); 127 hdidx[http2::HD_CONTENT_LENGTH] = 6; 128 rv = http2::get_header(hdidx, http2::HD_CONTENT_LENGTH, nva); 129 CU_ASSERT("content-length" == rv->name); 130} 131 132namespace { 133auto headers = HeaderRefs{ 134 {StringRef::from_lit("alpha"), StringRef::from_lit("0"), true}, 135 {StringRef::from_lit("bravo"), StringRef::from_lit("1")}, 136 {StringRef::from_lit("connection"), StringRef::from_lit("2"), false, 137 http2::HD_CONNECTION}, 138 {StringRef::from_lit("connection"), StringRef::from_lit("3"), false, 139 http2::HD_CONNECTION}, 140 {StringRef::from_lit("delta"), StringRef::from_lit("4")}, 141 {StringRef::from_lit("expect"), StringRef::from_lit("5")}, 142 {StringRef::from_lit("foxtrot"), StringRef::from_lit("6")}, 143 {StringRef::from_lit("tango"), StringRef::from_lit("7")}, 144 {StringRef::from_lit("te"), StringRef::from_lit("8"), false, http2::HD_TE}, 145 {StringRef::from_lit("te"), StringRef::from_lit("9"), false, http2::HD_TE}, 146 {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("10"), false, 147 http2::HD_X_FORWARDED_FOR}, 148 {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("11"), false, 149 http2::HD_X_FORWARDED_FOR}, 150 {StringRef::from_lit("zulu"), StringRef::from_lit("12")}}; 151} // namespace 152 153namespace { 154auto headers2 = HeaderRefs{ 155 {StringRef::from_lit("x-forwarded-for"), StringRef::from_lit("xff1"), false, 156 http2::HD_X_FORWARDED_FOR}, 157 {StringRef::from_lit("x-forwarded-for"), StringRef::from_lit("xff2"), false, 158 http2::HD_X_FORWARDED_FOR}, 159 {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("xfp1"), 160 false, http2::HD_X_FORWARDED_PROTO}, 161 {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("xfp2"), 162 false, http2::HD_X_FORWARDED_PROTO}, 163 {StringRef::from_lit("forwarded"), StringRef::from_lit("fwd1"), false, 164 http2::HD_FORWARDED}, 165 {StringRef::from_lit("forwarded"), StringRef::from_lit("fwd2"), false, 166 http2::HD_FORWARDED}, 167 {StringRef::from_lit("via"), StringRef::from_lit("via1"), false, 168 http2::HD_VIA}, 169 {StringRef::from_lit("via"), StringRef::from_lit("via2"), false, 170 http2::HD_VIA}, 171}; 172} // namespace 173 174void test_http2_copy_headers_to_nva(void) { 175 auto ans = std::vector<int>{0, 1, 4, 5, 6, 7, 12}; 176 std::vector<nghttp2_nv> nva; 177 178 http2::copy_headers_to_nva_nocopy(nva, headers, 179 http2::HDOP_STRIP_X_FORWARDED_FOR); 180 CU_ASSERT(7 == nva.size()); 181 for (size_t i = 0; i < ans.size(); ++i) { 182 check_nv(headers[ans[i]], &nva[i]); 183 184 if (ans[i] == 0) { 185 CU_ASSERT((NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE | 186 NGHTTP2_NV_FLAG_NO_INDEX) == nva[i].flags); 187 } else { 188 CU_ASSERT((NGHTTP2_NV_FLAG_NO_COPY_NAME | 189 NGHTTP2_NV_FLAG_NO_COPY_VALUE) == nva[i].flags); 190 } 191 } 192 193 nva.clear(); 194 http2::copy_headers_to_nva(nva, headers, http2::HDOP_STRIP_X_FORWARDED_FOR); 195 CU_ASSERT(7 == nva.size()); 196 for (size_t i = 0; i < ans.size(); ++i) { 197 check_nv(headers[ans[i]], &nva[i]); 198 199 if (ans[i] == 0) { 200 CU_ASSERT(nva[i].flags & NGHTTP2_NV_FLAG_NO_INDEX); 201 } else { 202 CU_ASSERT(NGHTTP2_NV_FLAG_NONE == nva[i].flags); 203 } 204 } 205 206 nva.clear(); 207 208 auto ans2 = std::vector<int>{0, 2, 4, 6}; 209 http2::copy_headers_to_nva(nva, headers2, http2::HDOP_NONE); 210 CU_ASSERT(ans2.size() == nva.size()); 211 for (size_t i = 0; i < ans2.size(); ++i) { 212 check_nv(headers2[ans2[i]], &nva[i]); 213 } 214 215 nva.clear(); 216 217 http2::copy_headers_to_nva(nva, headers2, http2::HDOP_STRIP_ALL); 218 CU_ASSERT(nva.empty()); 219} 220 221void test_http2_build_http1_headers_from_headers(void) { 222 MemchunkPool pool; 223 DefaultMemchunks buf(&pool); 224 http2::build_http1_headers_from_headers(&buf, headers, 225 http2::HDOP_STRIP_X_FORWARDED_FOR); 226 auto hdrs = std::string(buf.head->pos, buf.head->last); 227 CU_ASSERT("Alpha: 0\r\n" 228 "Bravo: 1\r\n" 229 "Delta: 4\r\n" 230 "Expect: 5\r\n" 231 "Foxtrot: 6\r\n" 232 "Tango: 7\r\n" 233 "Te: 8\r\n" 234 "Te: 9\r\n" 235 "Zulu: 12\r\n" == hdrs); 236 237 buf.reset(); 238 239 http2::build_http1_headers_from_headers(&buf, headers2, http2::HDOP_NONE); 240 hdrs = std::string(buf.head->pos, buf.head->last); 241 CU_ASSERT("X-Forwarded-For: xff1\r\n" 242 "X-Forwarded-Proto: xfp1\r\n" 243 "Forwarded: fwd1\r\n" 244 "Via: via1\r\n" == hdrs); 245 246 buf.reset(); 247 248 http2::build_http1_headers_from_headers(&buf, headers2, 249 http2::HDOP_STRIP_ALL); 250 CU_ASSERT(0 == buf.rleft()); 251} 252 253void test_http2_lws(void) { 254 CU_ASSERT(!http2::lws("alpha")); 255 CU_ASSERT(http2::lws(" ")); 256 CU_ASSERT(http2::lws("")); 257} 258 259namespace { 260void check_rewrite_location_uri(const std::string &want, const std::string &uri, 261 const std::string &match_host, 262 const std::string &req_authority, 263 const std::string &upstream_scheme) { 264 BlockAllocator balloc(4096, 4096); 265 http_parser_url u{}; 266 CU_ASSERT(0 == http_parser_parse_url(uri.c_str(), uri.size(), 0, &u)); 267 auto got = http2::rewrite_location_uri( 268 balloc, StringRef{uri}, u, StringRef{match_host}, 269 StringRef{req_authority}, StringRef{upstream_scheme}); 270 CU_ASSERT(want == got); 271} 272} // namespace 273 274void test_http2_rewrite_location_uri(void) { 275 check_rewrite_location_uri("https://localhost:3000/alpha?bravo#charlie", 276 "http://localhost:3001/alpha?bravo#charlie", 277 "localhost:3001", "localhost:3000", "https"); 278 check_rewrite_location_uri("https://localhost/", "http://localhost:3001/", 279 "localhost", "localhost", "https"); 280 check_rewrite_location_uri("http://localhost/", "http://localhost:3001/", 281 "localhost", "localhost", "http"); 282 check_rewrite_location_uri("http://localhost:443/", "http://localhost:3001/", 283 "localhost", "localhost:443", "http"); 284 check_rewrite_location_uri("https://localhost:80/", "http://localhost:3001/", 285 "localhost", "localhost:80", "https"); 286 check_rewrite_location_uri("", "http://localhost:3001/", "127.0.0.1", 287 "127.0.0.1", "https"); 288 check_rewrite_location_uri("https://localhost:3000/", 289 "http://localhost:3001/", "localhost", 290 "localhost:3000", "https"); 291 check_rewrite_location_uri("https://localhost:3000/", "http://localhost/", 292 "localhost", "localhost:3000", "https"); 293 294 // match_host != req_authority 295 check_rewrite_location_uri("https://example.org", "http://127.0.0.1:8080", 296 "127.0.0.1", "example.org", "https"); 297 check_rewrite_location_uri("", "http://example.org", "127.0.0.1", 298 "example.org", "https"); 299} 300 301void test_http2_parse_http_status_code(void) { 302 CU_ASSERT(200 == http2::parse_http_status_code(StringRef::from_lit("200"))); 303 CU_ASSERT(102 == http2::parse_http_status_code(StringRef::from_lit("102"))); 304 CU_ASSERT(-1 == http2::parse_http_status_code(StringRef::from_lit("099"))); 305 CU_ASSERT(-1 == http2::parse_http_status_code(StringRef::from_lit("99"))); 306 CU_ASSERT(-1 == http2::parse_http_status_code(StringRef::from_lit("-1"))); 307 CU_ASSERT(-1 == http2::parse_http_status_code(StringRef::from_lit("20a"))); 308 CU_ASSERT(-1 == http2::parse_http_status_code(StringRef{})); 309} 310 311void test_http2_index_header(void) { 312 http2::HeaderIndex hdidx; 313 http2::init_hdidx(hdidx); 314 315 http2::index_header(hdidx, http2::HD__AUTHORITY, 0); 316 http2::index_header(hdidx, -1, 1); 317 318 CU_ASSERT(0 == hdidx[http2::HD__AUTHORITY]); 319} 320 321void test_http2_lookup_token(void) { 322 CU_ASSERT(http2::HD__AUTHORITY == 323 http2::lookup_token(StringRef::from_lit(":authority"))); 324 CU_ASSERT(-1 == http2::lookup_token(StringRef::from_lit(":authorit"))); 325 CU_ASSERT(-1 == http2::lookup_token(StringRef::from_lit(":Authority"))); 326 CU_ASSERT(http2::HD_EXPECT == 327 http2::lookup_token(StringRef::from_lit("expect"))); 328} 329 330void test_http2_parse_link_header(void) { 331 { 332 // only URI appears; we don't extract URI unless it bears rel=preload 333 auto res = http2::parse_link_header(StringRef::from_lit("<url>")); 334 CU_ASSERT(0 == res.size()); 335 } 336 { 337 // URI url should be extracted 338 auto res = 339 http2::parse_link_header(StringRef::from_lit("<url>; rel=preload")); 340 CU_ASSERT(1 == res.size()); 341 CU_ASSERT("url" == res[0].uri); 342 } 343 { 344 // With extra link-param. URI url should be extracted 345 auto res = http2::parse_link_header( 346 StringRef::from_lit("<url>; rel=preload; as=file")); 347 CU_ASSERT(1 == res.size()); 348 CU_ASSERT("url" == res[0].uri); 349 } 350 { 351 // With extra link-param. URI url should be extracted 352 auto res = http2::parse_link_header( 353 StringRef::from_lit("<url>; as=file; rel=preload")); 354 CU_ASSERT(1 == res.size()); 355 CU_ASSERT("url" == res[0].uri); 356 } 357 { 358 // With extra link-param and quote-string. URI url should be 359 // extracted 360 auto res = http2::parse_link_header( 361 StringRef::from_lit(R"(<url>; rel=preload; title="foo,bar")")); 362 CU_ASSERT(1 == res.size()); 363 CU_ASSERT("url" == res[0].uri); 364 } 365 { 366 // With extra link-param and quote-string. URI url should be 367 // extracted 368 auto res = http2::parse_link_header( 369 StringRef::from_lit(R"(<url>; title="foo,bar"; rel=preload)")); 370 CU_ASSERT(1 == res.size()); 371 CU_ASSERT("url" == res[0].uri); 372 } 373 { 374 // ',' after quote-string 375 auto res = http2::parse_link_header( 376 StringRef::from_lit(R"(<url>; title="foo,bar", <url2>; rel=preload)")); 377 CU_ASSERT(1 == res.size()); 378 CU_ASSERT("url2" == res[0].uri); 379 } 380 { 381 // Only first URI should be extracted. 382 auto res = http2::parse_link_header( 383 StringRef::from_lit("<url>; rel=preload, <url2>")); 384 CU_ASSERT(1 == res.size()); 385 CU_ASSERT("url" == res[0].uri); 386 } 387 { 388 // Both have rel=preload, so both urls should be extracted 389 auto res = http2::parse_link_header( 390 StringRef::from_lit("<url>; rel=preload, <url2>; rel=preload")); 391 CU_ASSERT(2 == res.size()); 392 CU_ASSERT("url" == res[0].uri); 393 CU_ASSERT("url2" == res[1].uri); 394 } 395 { 396 // Second URI uri should be extracted. 397 auto res = http2::parse_link_header( 398 StringRef::from_lit("<url>, <url2>;rel=preload")); 399 CU_ASSERT(1 == res.size()); 400 CU_ASSERT("url2" == res[0].uri); 401 } 402 { 403 // Error if input ends with ';' 404 auto res = 405 http2::parse_link_header(StringRef::from_lit("<url>;rel=preload;")); 406 CU_ASSERT(0 == res.size()); 407 } 408 { 409 // Error if link header ends with ';' 410 auto res = http2::parse_link_header( 411 StringRef::from_lit("<url>;rel=preload;, <url>")); 412 CU_ASSERT(0 == res.size()); 413 } 414 { 415 // OK if input ends with ',' 416 auto res = 417 http2::parse_link_header(StringRef::from_lit("<url>;rel=preload,")); 418 CU_ASSERT(1 == res.size()); 419 CU_ASSERT("url" == res[0].uri); 420 } 421 { 422 // Multiple repeated ','s between fields is OK 423 auto res = http2::parse_link_header( 424 StringRef::from_lit("<url>,,,<url2>;rel=preload")); 425 CU_ASSERT(1 == res.size()); 426 CU_ASSERT("url2" == res[0].uri); 427 } 428 { 429 // Error if url is not enclosed by <> 430 auto res = 431 http2::parse_link_header(StringRef::from_lit("url>;rel=preload")); 432 CU_ASSERT(0 == res.size()); 433 } 434 { 435 // Error if url is not enclosed by <> 436 auto res = 437 http2::parse_link_header(StringRef::from_lit("<url;rel=preload")); 438 CU_ASSERT(0 == res.size()); 439 } 440 { 441 // Empty parameter value is not allowed 442 auto res = 443 http2::parse_link_header(StringRef::from_lit("<url>;rel=preload; as=")); 444 CU_ASSERT(0 == res.size()); 445 } 446 { 447 // Empty parameter value is not allowed 448 auto res = 449 http2::parse_link_header(StringRef::from_lit("<url>;as=;rel=preload")); 450 CU_ASSERT(0 == res.size()); 451 } 452 { 453 // Empty parameter value is not allowed 454 auto res = http2::parse_link_header( 455 StringRef::from_lit("<url>;as=, <url>;rel=preload")); 456 CU_ASSERT(0 == res.size()); 457 } 458 { 459 // Empty parameter name is not allowed 460 auto res = http2::parse_link_header( 461 StringRef::from_lit("<url>; =file; rel=preload")); 462 CU_ASSERT(0 == res.size()); 463 } 464 { 465 // Without whitespaces 466 auto res = http2::parse_link_header( 467 StringRef::from_lit("<url>;as=file;rel=preload,<url2>;rel=preload")); 468 CU_ASSERT(2 == res.size()); 469 CU_ASSERT("url" == res[0].uri); 470 CU_ASSERT("url2" == res[1].uri); 471 } 472 { 473 // link-extension may have no value 474 auto res = 475 http2::parse_link_header(StringRef::from_lit("<url>; as; rel=preload")); 476 CU_ASSERT(1 == res.size()); 477 CU_ASSERT("url" == res[0].uri); 478 } 479 { 480 // ext-name-star 481 auto res = http2::parse_link_header( 482 StringRef::from_lit("<url>; foo*=bar; rel=preload")); 483 CU_ASSERT(1 == res.size()); 484 CU_ASSERT("url" == res[0].uri); 485 } 486 { 487 // '*' is not allowed expect for trailing one 488 auto res = http2::parse_link_header( 489 StringRef::from_lit("<url>; *=bar; rel=preload")); 490 CU_ASSERT(0 == res.size()); 491 } 492 { 493 // '*' is not allowed expect for trailing one 494 auto res = http2::parse_link_header( 495 StringRef::from_lit("<url>; foo*bar=buzz; rel=preload")); 496 CU_ASSERT(0 == res.size()); 497 } 498 { 499 // ext-name-star must be followed by '=' 500 auto res = http2::parse_link_header( 501 StringRef::from_lit("<url>; foo*; rel=preload")); 502 CU_ASSERT(0 == res.size()); 503 } 504 { 505 // '>' is not followed by ';' 506 auto res = 507 http2::parse_link_header(StringRef::from_lit("<url> rel=preload")); 508 CU_ASSERT(0 == res.size()); 509 } 510 { 511 // Starting with whitespace is no problem. 512 auto res = 513 http2::parse_link_header(StringRef::from_lit(" <url>; rel=preload")); 514 CU_ASSERT(1 == res.size()); 515 CU_ASSERT("url" == res[0].uri); 516 } 517 { 518 // preload is a prefix of bogus rel parameter value 519 auto res = 520 http2::parse_link_header(StringRef::from_lit("<url>; rel=preloadx")); 521 CU_ASSERT(0 == res.size()); 522 } 523 { 524 // preload in relation-types list 525 auto res = http2::parse_link_header( 526 StringRef::from_lit(R"(<url>; rel="preload")")); 527 CU_ASSERT(1 == res.size()); 528 CU_ASSERT("url" == res[0].uri); 529 } 530 { 531 // preload in relation-types list followed by another parameter 532 auto res = http2::parse_link_header( 533 StringRef::from_lit(R"(<url>; rel="preload foo")")); 534 CU_ASSERT(1 == res.size()); 535 CU_ASSERT("url" == res[0].uri); 536 } 537 { 538 // preload in relation-types list following another parameter 539 auto res = http2::parse_link_header( 540 StringRef::from_lit(R"(<url>; rel="foo preload")")); 541 CU_ASSERT(1 == res.size()); 542 CU_ASSERT("url" == res[0].uri); 543 } 544 { 545 // preload in relation-types list between other parameters 546 auto res = http2::parse_link_header( 547 StringRef::from_lit(R"(<url>; rel="foo preload bar")")); 548 CU_ASSERT(1 == res.size()); 549 CU_ASSERT("url" == res[0].uri); 550 } 551 { 552 // preload in relation-types list between other parameters 553 auto res = http2::parse_link_header( 554 StringRef::from_lit(R"(<url>; rel="foo preload bar")")); 555 CU_ASSERT(1 == res.size()); 556 CU_ASSERT("url" == res[0].uri); 557 } 558 { 559 // no preload in relation-types list 560 auto res = 561 http2::parse_link_header(StringRef::from_lit(R"(<url>; rel="foo")")); 562 CU_ASSERT(0 == res.size()); 563 } 564 { 565 // no preload in relation-types list, multiple unrelated elements. 566 auto res = http2::parse_link_header( 567 StringRef::from_lit(R"(<url>; rel="foo bar")")); 568 CU_ASSERT(0 == res.size()); 569 } 570 { 571 // preload in relation-types list, followed by another link-value. 572 auto res = http2::parse_link_header( 573 StringRef::from_lit(R"(<url>; rel="preload", <url2>)")); 574 CU_ASSERT(1 == res.size()); 575 CU_ASSERT("url" == res[0].uri); 576 } 577 { 578 // preload in relation-types list, following another link-value. 579 auto res = http2::parse_link_header( 580 StringRef::from_lit(R"(<url>, <url2>; rel="preload")")); 581 CU_ASSERT(1 == res.size()); 582 CU_ASSERT("url2" == res[0].uri); 583 } 584 { 585 // preload in relation-types list, followed by another link-param. 586 auto res = http2::parse_link_header( 587 StringRef::from_lit(R"(<url>; rel="preload"; as="font")")); 588 CU_ASSERT(1 == res.size()); 589 CU_ASSERT("url" == res[0].uri); 590 } 591 { 592 // preload in relation-types list, followed by character other 593 // than ';' or ',' 594 auto res = http2::parse_link_header( 595 StringRef::from_lit(R"(<url>; rel="preload".)")); 596 CU_ASSERT(0 == res.size()); 597 } 598 { 599 // preload in relation-types list, followed by ';' but it 600 // terminates input 601 auto res = http2::parse_link_header( 602 StringRef::from_lit(R"(<url>; rel="preload";)")); 603 CU_ASSERT(0 == res.size()); 604 } 605 { 606 // preload in relation-types list, followed by ',' but it 607 // terminates input 608 auto res = http2::parse_link_header( 609 StringRef::from_lit(R"(<url>; rel="preload",)")); 610 CU_ASSERT(1 == res.size()); 611 CU_ASSERT("url" == res[0].uri); 612 } 613 { 614 // preload in relation-types list but there is preceding white 615 // space. 616 auto res = http2::parse_link_header( 617 StringRef::from_lit(R"(<url>; rel=" preload")")); 618 CU_ASSERT(0 == res.size()); 619 } 620 { 621 // preload in relation-types list but there is trailing white 622 // space. 623 auto res = http2::parse_link_header( 624 StringRef::from_lit(R"(<url>; rel="preload ")")); 625 CU_ASSERT(0 == res.size()); 626 } 627 { 628 // backslash escaped characters in quoted-string 629 auto res = http2::parse_link_header( 630 StringRef::from_lit(R"(<url>; rel=preload; title="foo\"baz\"bar")")); 631 CU_ASSERT(1 == res.size()); 632 CU_ASSERT("url" == res[0].uri); 633 } 634 { 635 // anchor="" is acceptable 636 auto res = http2::parse_link_header( 637 StringRef::from_lit(R"(<url>; rel=preload; anchor="")")); 638 CU_ASSERT(1 == res.size()); 639 CU_ASSERT("url" == res[0].uri); 640 } 641 { 642 // With anchor="#foo", url should be ignored 643 auto res = http2::parse_link_header( 644 StringRef::from_lit(R"(<url>; rel=preload; anchor="#foo")")); 645 CU_ASSERT(0 == res.size()); 646 } 647 { 648 // With anchor=f, url should be ignored 649 auto res = http2::parse_link_header( 650 StringRef::from_lit("<url>; rel=preload; anchor=f")); 651 CU_ASSERT(0 == res.size()); 652 } 653 { 654 // First url is ignored With anchor="#foo", but url should be 655 // accepted. 656 auto res = http2::parse_link_header(StringRef::from_lit( 657 R"(<url>; rel=preload; anchor="#foo", <url2>; rel=preload)")); 658 CU_ASSERT(1 == res.size()); 659 CU_ASSERT("url2" == res[0].uri); 660 } 661 { 662 // With loadpolicy="next", url should be ignored 663 auto res = http2::parse_link_header( 664 StringRef::from_lit(R"(<url>; rel=preload; loadpolicy="next")")); 665 CU_ASSERT(0 == res.size()); 666 } 667 { 668 // url should be picked up if empty loadpolicy is specified 669 auto res = http2::parse_link_header( 670 StringRef::from_lit(R"(<url>; rel=preload; loadpolicy="")")); 671 CU_ASSERT(1 == res.size()); 672 CU_ASSERT("url" == res[0].uri); 673 } 674 { 675 // case-insensitive match 676 auto res = http2::parse_link_header( 677 StringRef::from_lit(R"(<url>; rel=preload; ANCHOR="#foo", <url2>; )" 678 R"(REL=PRELOAD, <url3>; REL="foo PRELOAD bar")")); 679 CU_ASSERT(2 == res.size()); 680 CU_ASSERT("url2" == res[0].uri); 681 CU_ASSERT("url3" == res[1].uri); 682 } 683 { 684 // nopush at the end of input 685 auto res = http2::parse_link_header( 686 StringRef::from_lit("<url>; rel=preload; nopush")); 687 CU_ASSERT(0 == res.size()); 688 } 689 { 690 // nopush followed by ';' 691 auto res = http2::parse_link_header( 692 StringRef::from_lit("<url>; rel=preload; nopush; foo")); 693 CU_ASSERT(0 == res.size()); 694 } 695 { 696 // nopush followed by ',' 697 auto res = http2::parse_link_header( 698 StringRef::from_lit("<url>; nopush; rel=preload")); 699 CU_ASSERT(0 == res.size()); 700 } 701 { 702 // string whose prefix is nopush 703 auto res = http2::parse_link_header( 704 StringRef::from_lit("<url>; nopushyes; rel=preload")); 705 CU_ASSERT(1 == res.size()); 706 CU_ASSERT("url" == res[0].uri); 707 } 708 { 709 // rel=preload twice 710 auto res = http2::parse_link_header( 711 StringRef::from_lit("<url>; rel=preload; rel=preload")); 712 CU_ASSERT(1 == res.size()); 713 CU_ASSERT("url" == res[0].uri); 714 } 715} 716 717void test_http2_path_join(void) { 718 { 719 auto base = StringRef::from_lit("/"); 720 auto rel = StringRef::from_lit("/"); 721 CU_ASSERT("/" == http2::path_join(base, StringRef{}, rel, StringRef{})); 722 } 723 { 724 auto base = StringRef::from_lit("/"); 725 auto rel = StringRef::from_lit("/alpha"); 726 CU_ASSERT("/alpha" == 727 http2::path_join(base, StringRef{}, rel, StringRef{})); 728 } 729 { 730 // rel ends with trailing '/' 731 auto base = StringRef::from_lit("/"); 732 auto rel = StringRef::from_lit("/alpha/"); 733 CU_ASSERT("/alpha/" == 734 http2::path_join(base, StringRef{}, rel, StringRef{})); 735 } 736 { 737 // rel contains multiple components 738 auto base = StringRef::from_lit("/"); 739 auto rel = StringRef::from_lit("/alpha/bravo"); 740 CU_ASSERT("/alpha/bravo" == 741 http2::path_join(base, StringRef{}, rel, StringRef{})); 742 } 743 { 744 // rel is relative 745 auto base = StringRef::from_lit("/"); 746 auto rel = StringRef::from_lit("alpha/bravo"); 747 CU_ASSERT("/alpha/bravo" == 748 http2::path_join(base, StringRef{}, rel, StringRef{})); 749 } 750 { 751 // rel is relative and base ends without /, which means it refers 752 // to file. 753 auto base = StringRef::from_lit("/alpha"); 754 auto rel = StringRef::from_lit("bravo/charlie"); 755 CU_ASSERT("/bravo/charlie" == 756 http2::path_join(base, StringRef{}, rel, StringRef{})); 757 } 758 { 759 // rel contains repeated '/'s 760 auto base = StringRef::from_lit("/"); 761 auto rel = StringRef::from_lit("/alpha/////bravo/////"); 762 CU_ASSERT("/alpha/bravo/" == 763 http2::path_join(base, StringRef{}, rel, StringRef{})); 764 } 765 { 766 // base ends with '/', so '..' eats 'bravo' 767 auto base = StringRef::from_lit("/alpha/bravo/"); 768 auto rel = StringRef::from_lit("../charlie/delta"); 769 CU_ASSERT("/alpha/charlie/delta" == 770 http2::path_join(base, StringRef{}, rel, StringRef{})); 771 } 772 { 773 // base does not end with '/', so '..' eats 'alpha/bravo' 774 auto base = StringRef::from_lit("/alpha/bravo"); 775 auto rel = StringRef::from_lit("../charlie"); 776 CU_ASSERT("/charlie" == 777 http2::path_join(base, StringRef{}, rel, StringRef{})); 778 } 779 { 780 // 'charlie' is eaten by following '..' 781 auto base = StringRef::from_lit("/alpha/bravo/"); 782 auto rel = StringRef::from_lit("../charlie/../delta"); 783 CU_ASSERT("/alpha/delta" == 784 http2::path_join(base, StringRef{}, rel, StringRef{})); 785 } 786 { 787 // excessive '..' results in '/' 788 auto base = StringRef::from_lit("/alpha/bravo/"); 789 auto rel = StringRef::from_lit("../../../"); 790 CU_ASSERT("/" == http2::path_join(base, StringRef{}, rel, StringRef{})); 791 } 792 { 793 // excessive '..' and path component 794 auto base = StringRef::from_lit("/alpha/bravo/"); 795 auto rel = StringRef::from_lit("../../../charlie"); 796 CU_ASSERT("/charlie" == 797 http2::path_join(base, StringRef{}, rel, StringRef{})); 798 } 799 { 800 // rel ends with '..' 801 auto base = StringRef::from_lit("/alpha/bravo/"); 802 auto rel = StringRef::from_lit("charlie/.."); 803 CU_ASSERT("/alpha/bravo/" == 804 http2::path_join(base, StringRef{}, rel, StringRef{})); 805 } 806 { 807 // base empty and rel contains '..' 808 auto base = StringRef{}; 809 auto rel = StringRef::from_lit("charlie/.."); 810 CU_ASSERT("/" == http2::path_join(base, StringRef{}, rel, StringRef{})); 811 } 812 { 813 // '.' is ignored 814 auto base = StringRef::from_lit("/"); 815 auto rel = StringRef::from_lit("charlie/././././delta"); 816 CU_ASSERT("/charlie/delta" == 817 http2::path_join(base, StringRef{}, rel, StringRef{})); 818 } 819 { 820 // trailing '.' is ignored 821 auto base = StringRef::from_lit("/"); 822 auto rel = StringRef::from_lit("charlie/."); 823 CU_ASSERT("/charlie/" == 824 http2::path_join(base, StringRef{}, rel, StringRef{})); 825 } 826 { 827 // query 828 auto base = StringRef::from_lit("/"); 829 auto rel = StringRef::from_lit("/"); 830 auto relq = StringRef::from_lit("q"); 831 CU_ASSERT("/?q" == http2::path_join(base, StringRef{}, rel, relq)); 832 } 833 { 834 // empty rel and query 835 auto base = StringRef::from_lit("/alpha"); 836 auto rel = StringRef{}; 837 auto relq = StringRef::from_lit("q"); 838 CU_ASSERT("/alpha?q" == http2::path_join(base, StringRef{}, rel, relq)); 839 } 840 { 841 // both rel and query are empty 842 auto base = StringRef::from_lit("/alpha"); 843 auto baseq = StringRef::from_lit("r"); 844 auto rel = StringRef{}; 845 auto relq = StringRef{}; 846 CU_ASSERT("/alpha?r" == http2::path_join(base, baseq, rel, relq)); 847 } 848 { 849 // empty base 850 auto base = StringRef{}; 851 auto rel = StringRef::from_lit("/alpha"); 852 CU_ASSERT("/alpha" == 853 http2::path_join(base, StringRef{}, rel, StringRef{})); 854 } 855 { 856 // everything is empty 857 CU_ASSERT("/" == http2::path_join(StringRef{}, StringRef{}, StringRef{}, 858 StringRef{})); 859 } 860 { 861 // only baseq is not empty 862 auto base = StringRef{}; 863 auto baseq = StringRef::from_lit("r"); 864 auto rel = StringRef{}; 865 CU_ASSERT("/?r" == http2::path_join(base, baseq, rel, StringRef{})); 866 } 867 { 868 // path starts with multiple '/'s. 869 auto base = StringRef{}; 870 auto baseq = StringRef{}; 871 auto rel = StringRef::from_lit("//alpha//bravo"); 872 auto relq = StringRef::from_lit("charlie"); 873 CU_ASSERT("/alpha/bravo?charlie" == 874 http2::path_join(base, baseq, rel, relq)); 875 } 876 // Test cases from RFC 3986, section 5.4. 877 constexpr auto base = StringRef::from_lit("/b/c/d;p"); 878 constexpr auto baseq = StringRef::from_lit("q"); 879 { 880 auto rel = StringRef::from_lit("g"); 881 auto relq = StringRef{}; 882 CU_ASSERT("/b/c/g" == http2::path_join(base, baseq, rel, relq)); 883 } 884 { 885 auto rel = StringRef::from_lit("./g"); 886 auto relq = StringRef{}; 887 CU_ASSERT("/b/c/g" == http2::path_join(base, baseq, rel, relq)); 888 } 889 { 890 auto rel = StringRef::from_lit("g/"); 891 auto relq = StringRef{}; 892 CU_ASSERT("/b/c/g/" == http2::path_join(base, baseq, rel, relq)); 893 } 894 { 895 auto rel = StringRef::from_lit("/g"); 896 auto relq = StringRef{}; 897 CU_ASSERT("/g" == http2::path_join(base, baseq, rel, relq)); 898 } 899 { 900 auto rel = StringRef{}; 901 auto relq = StringRef::from_lit("y"); 902 CU_ASSERT("/b/c/d;p?y" == http2::path_join(base, baseq, rel, relq)); 903 } 904 { 905 auto rel = StringRef::from_lit("g"); 906 auto relq = StringRef::from_lit("y"); 907 CU_ASSERT("/b/c/g?y" == http2::path_join(base, baseq, rel, relq)); 908 } 909 { 910 auto rel = StringRef::from_lit(";x"); 911 auto relq = StringRef{}; 912 CU_ASSERT("/b/c/;x" == http2::path_join(base, baseq, rel, relq)); 913 } 914 { 915 auto rel = StringRef::from_lit("g;x"); 916 auto relq = StringRef{}; 917 CU_ASSERT("/b/c/g;x" == http2::path_join(base, baseq, rel, relq)); 918 } 919 { 920 auto rel = StringRef::from_lit("g;x"); 921 auto relq = StringRef::from_lit("y"); 922 CU_ASSERT("/b/c/g;x?y" == http2::path_join(base, baseq, rel, relq)); 923 } 924 { 925 auto rel = StringRef{}; 926 auto relq = StringRef{}; 927 CU_ASSERT("/b/c/d;p?q" == http2::path_join(base, baseq, rel, relq)); 928 } 929 { 930 auto rel = StringRef::from_lit("."); 931 auto relq = StringRef{}; 932 CU_ASSERT("/b/c/" == http2::path_join(base, baseq, rel, relq)); 933 } 934 { 935 auto rel = StringRef::from_lit("./"); 936 auto relq = StringRef{}; 937 CU_ASSERT("/b/c/" == http2::path_join(base, baseq, rel, relq)); 938 } 939 { 940 auto rel = StringRef::from_lit(".."); 941 auto relq = StringRef{}; 942 CU_ASSERT("/b/" == http2::path_join(base, baseq, rel, relq)); 943 } 944 { 945 auto rel = StringRef::from_lit("../"); 946 auto relq = StringRef{}; 947 CU_ASSERT("/b/" == http2::path_join(base, baseq, rel, relq)); 948 } 949 { 950 auto rel = StringRef::from_lit("../g"); 951 auto relq = StringRef{}; 952 CU_ASSERT("/b/g" == http2::path_join(base, baseq, rel, relq)); 953 } 954 { 955 auto rel = StringRef::from_lit("../.."); 956 auto relq = StringRef{}; 957 CU_ASSERT("/" == http2::path_join(base, baseq, rel, relq)); 958 } 959 { 960 auto rel = StringRef::from_lit("../../"); 961 auto relq = StringRef{}; 962 CU_ASSERT("/" == http2::path_join(base, baseq, rel, relq)); 963 } 964 { 965 auto rel = StringRef::from_lit("../../g"); 966 auto relq = StringRef{}; 967 CU_ASSERT("/g" == http2::path_join(base, baseq, rel, relq)); 968 } 969 { 970 auto rel = StringRef::from_lit("../../../g"); 971 auto relq = StringRef{}; 972 CU_ASSERT("/g" == http2::path_join(base, baseq, rel, relq)); 973 } 974 { 975 auto rel = StringRef::from_lit("../../../../g"); 976 auto relq = StringRef{}; 977 CU_ASSERT("/g" == http2::path_join(base, baseq, rel, relq)); 978 } 979 { 980 auto rel = StringRef::from_lit("/./g"); 981 auto relq = StringRef{}; 982 CU_ASSERT("/g" == http2::path_join(base, baseq, rel, relq)); 983 } 984 { 985 auto rel = StringRef::from_lit("/../g"); 986 auto relq = StringRef{}; 987 CU_ASSERT("/g" == http2::path_join(base, baseq, rel, relq)); 988 } 989 { 990 auto rel = StringRef::from_lit("g."); 991 auto relq = StringRef{}; 992 CU_ASSERT("/b/c/g." == http2::path_join(base, baseq, rel, relq)); 993 } 994 { 995 auto rel = StringRef::from_lit(".g"); 996 auto relq = StringRef{}; 997 CU_ASSERT("/b/c/.g" == http2::path_join(base, baseq, rel, relq)); 998 } 999 { 1000 auto rel = StringRef::from_lit("g.."); 1001 auto relq = StringRef{}; 1002 CU_ASSERT("/b/c/g.." == http2::path_join(base, baseq, rel, relq)); 1003 } 1004 { 1005 auto rel = StringRef::from_lit("..g"); 1006 auto relq = StringRef{}; 1007 CU_ASSERT("/b/c/..g" == http2::path_join(base, baseq, rel, relq)); 1008 } 1009 { 1010 auto rel = StringRef::from_lit("./../g"); 1011 auto relq = StringRef{}; 1012 CU_ASSERT("/b/g" == http2::path_join(base, baseq, rel, relq)); 1013 } 1014 { 1015 auto rel = StringRef::from_lit("./g/."); 1016 auto relq = StringRef{}; 1017 CU_ASSERT("/b/c/g/" == http2::path_join(base, baseq, rel, relq)); 1018 } 1019 { 1020 auto rel = StringRef::from_lit("g/./h"); 1021 auto relq = StringRef{}; 1022 CU_ASSERT("/b/c/g/h" == http2::path_join(base, baseq, rel, relq)); 1023 } 1024 { 1025 auto rel = StringRef::from_lit("g/../h"); 1026 auto relq = StringRef{}; 1027 CU_ASSERT("/b/c/h" == http2::path_join(base, baseq, rel, relq)); 1028 } 1029 { 1030 auto rel = StringRef::from_lit("g;x=1/./y"); 1031 auto relq = StringRef{}; 1032 CU_ASSERT("/b/c/g;x=1/y" == http2::path_join(base, baseq, rel, relq)); 1033 } 1034 { 1035 auto rel = StringRef::from_lit("g;x=1/../y"); 1036 auto relq = StringRef{}; 1037 CU_ASSERT("/b/c/y" == http2::path_join(base, baseq, rel, relq)); 1038 } 1039} 1040 1041void test_http2_normalize_path(void) { 1042 CU_ASSERT("/alpha/charlie" == 1043 http2::normalize_path( 1044 StringRef::from_lit("/alpha/bravo/../charlie"), StringRef{})); 1045 1046 CU_ASSERT("/alpha" == 1047 http2::normalize_path(StringRef::from_lit("/a%6c%70%68%61"), 1048 StringRef{})); 1049 1050 CU_ASSERT( 1051 "/alpha%2F%3A" == 1052 http2::normalize_path(StringRef::from_lit("/alpha%2f%3a"), StringRef{})); 1053 1054 CU_ASSERT("/%2F" == 1055 http2::normalize_path(StringRef::from_lit("%2f"), StringRef{})); 1056 1057 CU_ASSERT("/%f" == 1058 http2::normalize_path(StringRef::from_lit("%f"), StringRef{})); 1059 1060 CU_ASSERT("/%" == 1061 http2::normalize_path(StringRef::from_lit("%"), StringRef{})); 1062 1063 CU_ASSERT("/" == http2::normalize_path(StringRef{}, StringRef{})); 1064 1065 CU_ASSERT("/alpha?bravo" == 1066 http2::normalize_path(StringRef::from_lit("/alpha"), 1067 StringRef::from_lit("bravo"))); 1068} 1069 1070void test_http2_rewrite_clean_path(void) { 1071 BlockAllocator balloc(4096, 4096); 1072 1073 // unreserved characters 1074 CU_ASSERT("/alpha/bravo/" == 1075 http2::rewrite_clean_path(balloc, 1076 StringRef::from_lit("/alpha/%62ravo/"))); 1077 1078 // percent-encoding is converted to upper case. 1079 CU_ASSERT("/delta%3A" == http2::rewrite_clean_path( 1080 balloc, StringRef::from_lit("/delta%3a"))); 1081 1082 // path component is normalized before matching 1083 CU_ASSERT( 1084 "/alpha/bravo/" == 1085 http2::rewrite_clean_path( 1086 balloc, StringRef::from_lit("/alpha/charlie/%2e././bravo/delta/.."))); 1087 1088 CU_ASSERT("alpha%3a" == 1089 http2::rewrite_clean_path(balloc, StringRef::from_lit("alpha%3a"))); 1090 1091 CU_ASSERT("" == http2::rewrite_clean_path(balloc, StringRef{})); 1092 1093 CU_ASSERT( 1094 "/alpha?bravo" == 1095 http2::rewrite_clean_path(balloc, StringRef::from_lit("//alpha?bravo"))); 1096} 1097 1098void test_http2_get_pure_path_component(void) { 1099 CU_ASSERT("/" == http2::get_pure_path_component(StringRef::from_lit("/"))); 1100 1101 CU_ASSERT("/foo" == 1102 http2::get_pure_path_component(StringRef::from_lit("/foo"))); 1103 1104 CU_ASSERT("/bar" == http2::get_pure_path_component( 1105 StringRef::from_lit("https://example.org/bar"))); 1106 1107 CU_ASSERT("/alpha" == http2::get_pure_path_component(StringRef::from_lit( 1108 "https://example.org/alpha?q=a"))); 1109 1110 CU_ASSERT("/bravo" == http2::get_pure_path_component(StringRef::from_lit( 1111 "https://example.org/bravo?q=a#fragment"))); 1112 1113 CU_ASSERT("" == 1114 http2::get_pure_path_component(StringRef::from_lit("\x01\x02"))); 1115} 1116 1117void test_http2_construct_push_component(void) { 1118 BlockAllocator balloc(4096, 4096); 1119 StringRef base, uri; 1120 StringRef scheme, authority, path; 1121 1122 base = StringRef::from_lit("/b/"); 1123 uri = StringRef::from_lit("https://example.org/foo"); 1124 1125 CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority, 1126 path, base, uri)); 1127 CU_ASSERT("https" == scheme); 1128 CU_ASSERT("example.org" == authority); 1129 CU_ASSERT("/foo" == path); 1130 1131 scheme = StringRef{}; 1132 authority = StringRef{}; 1133 path = StringRef{}; 1134 1135 uri = StringRef::from_lit("/foo/bar?q=a"); 1136 1137 CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority, 1138 path, base, uri)); 1139 CU_ASSERT("" == scheme); 1140 CU_ASSERT("" == authority); 1141 CU_ASSERT("/foo/bar?q=a" == path); 1142 1143 scheme = StringRef{}; 1144 authority = StringRef{}; 1145 path = StringRef{}; 1146 1147 uri = StringRef::from_lit("foo/../bar?q=a"); 1148 1149 CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority, 1150 path, base, uri)); 1151 CU_ASSERT("" == scheme); 1152 CU_ASSERT("" == authority); 1153 CU_ASSERT("/b/bar?q=a" == path); 1154 1155 scheme = StringRef{}; 1156 authority = StringRef{}; 1157 path = StringRef{}; 1158 1159 uri = StringRef{}; 1160 1161 CU_ASSERT(-1 == http2::construct_push_component(balloc, scheme, authority, 1162 path, base, uri)); 1163 scheme = StringRef{}; 1164 authority = StringRef{}; 1165 path = StringRef{}; 1166 1167 uri = StringRef::from_lit("?q=a"); 1168 1169 CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority, 1170 path, base, uri)); 1171 CU_ASSERT("" == scheme); 1172 CU_ASSERT("" == authority); 1173 CU_ASSERT("/b/?q=a" == path); 1174} 1175 1176void test_http2_contains_trailers(void) { 1177 CU_ASSERT(!http2::contains_trailers(StringRef::from_lit(""))); 1178 CU_ASSERT(http2::contains_trailers(StringRef::from_lit("trailers"))); 1179 // Match must be case-insensitive. 1180 CU_ASSERT(http2::contains_trailers(StringRef::from_lit("TRAILERS"))); 1181 CU_ASSERT(!http2::contains_trailers(StringRef::from_lit("trailer"))); 1182 CU_ASSERT(!http2::contains_trailers(StringRef::from_lit("trailers 3"))); 1183 CU_ASSERT(http2::contains_trailers(StringRef::from_lit("trailers,"))); 1184 CU_ASSERT(http2::contains_trailers(StringRef::from_lit("trailers,foo"))); 1185 CU_ASSERT(http2::contains_trailers(StringRef::from_lit("foo,trailers"))); 1186 CU_ASSERT(http2::contains_trailers(StringRef::from_lit("foo,trailers,bar"))); 1187 CU_ASSERT( 1188 http2::contains_trailers(StringRef::from_lit("foo, trailers ,bar"))); 1189 CU_ASSERT(http2::contains_trailers(StringRef::from_lit(",trailers"))); 1190} 1191 1192void test_http2_check_transfer_encoding(void) { 1193 CU_ASSERT(http2::check_transfer_encoding(StringRef::from_lit("chunked"))); 1194 CU_ASSERT(http2::check_transfer_encoding(StringRef::from_lit("foo,chunked"))); 1195 CU_ASSERT( 1196 http2::check_transfer_encoding(StringRef::from_lit("foo, chunked"))); 1197 CU_ASSERT( 1198 http2::check_transfer_encoding(StringRef::from_lit("foo , chunked"))); 1199 CU_ASSERT( 1200 http2::check_transfer_encoding(StringRef::from_lit("chunked;foo=bar"))); 1201 CU_ASSERT( 1202 http2::check_transfer_encoding(StringRef::from_lit("chunked ; foo=bar"))); 1203 CU_ASSERT(http2::check_transfer_encoding( 1204 StringRef::from_lit(R"(chunked;foo="bar")"))); 1205 CU_ASSERT(http2::check_transfer_encoding( 1206 StringRef::from_lit(R"(chunked;foo="\bar\"";FOO=BAR)"))); 1207 CU_ASSERT( 1208 http2::check_transfer_encoding(StringRef::from_lit(R"(chunked;foo="")"))); 1209 CU_ASSERT(http2::check_transfer_encoding( 1210 StringRef::from_lit(R"(chunked;foo="bar" , gzip)"))); 1211 1212 CU_ASSERT(!http2::check_transfer_encoding(StringRef{})); 1213 CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit(",chunked"))); 1214 CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked,"))); 1215 CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked, "))); 1216 CU_ASSERT( 1217 !http2::check_transfer_encoding(StringRef::from_lit("foo,,chunked"))); 1218 CU_ASSERT( 1219 !http2::check_transfer_encoding(StringRef::from_lit("chunked;foo"))); 1220 CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked;"))); 1221 CU_ASSERT( 1222 !http2::check_transfer_encoding(StringRef::from_lit("chunked;foo=bar;"))); 1223 CU_ASSERT( 1224 !http2::check_transfer_encoding(StringRef::from_lit("chunked;?=bar"))); 1225 CU_ASSERT( 1226 !http2::check_transfer_encoding(StringRef::from_lit("chunked;=bar"))); 1227 CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked;;"))); 1228 CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked?"))); 1229 CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit(","))); 1230 CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit(" "))); 1231 CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit(";"))); 1232 CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("\""))); 1233 CU_ASSERT(!http2::check_transfer_encoding( 1234 StringRef::from_lit(R"(chunked;foo="bar)"))); 1235 CU_ASSERT(!http2::check_transfer_encoding( 1236 StringRef::from_lit(R"(chunked;foo="bar\)"))); 1237 CU_ASSERT( 1238 !http2::check_transfer_encoding(StringRef::from_lit(R"(chunked;foo="bar\)" 1239 "\x0a" 1240 R"(")"))); 1241 CU_ASSERT( 1242 !http2::check_transfer_encoding(StringRef::from_lit(R"(chunked;foo=")" 1243 "\x0a" 1244 R"(")"))); 1245 CU_ASSERT(!http2::check_transfer_encoding( 1246 StringRef::from_lit(R"(chunked;foo="bar",,gzip)"))); 1247} 1248 1249} // namespace shrpx 1250