summaryrefslogtreecommitdiff
path: root/vendor/httparse
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-15 16:37:08 -0600
committermo khan <mo@mokhan.ca>2025-07-17 16:30:22 -0600
commit45df4d0d9b577fecee798d672695fe24ff57fb1b (patch)
tree1b99bf645035b58e0d6db08c7a83521f41f7a75b /vendor/httparse
parentf94f79608393d4ab127db63cc41668445ef6b243 (diff)
feat: migrate from Cedar to SpiceDB authorization system
This is a major architectural change that replaces the Cedar policy-based authorization system with SpiceDB's relation-based authorization. Key changes: - Migrate from Rust to Go implementation - Replace Cedar policies with SpiceDB schema and relationships - Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks - Update build system and dependencies for Go ecosystem - Maintain Envoy integration for external authorization This change enables more flexible permission modeling through SpiceDB's Google Zanzibar inspired relation-based system, supporting complex hierarchical permissions that were difficult to express in Cedar. Breaking change: Existing Cedar policies and Rust-based configuration will no longer work and need to be migrated to SpiceDB schema.
Diffstat (limited to 'vendor/httparse')
-rw-r--r--vendor/httparse/.cargo-checksum.json1
-rw-r--r--vendor/httparse/Cargo.lock688
-rw-r--r--vendor/httparse/Cargo.toml77
-rw-r--r--vendor/httparse/LICENSE-APACHE201
-rw-r--r--vendor/httparse/LICENSE-MIT20
-rw-r--r--vendor/httparse/README.md43
-rw-r--r--vendor/httparse/benches/parse.rs242
-rw-r--r--vendor/httparse/build.rs133
-rw-r--r--vendor/httparse/clippy.toml1
-rw-r--r--vendor/httparse/src/iter.rs199
-rw-r--r--vendor/httparse/src/lib.rs2798
-rw-r--r--vendor/httparse/src/macros.rs68
-rw-r--r--vendor/httparse/src/simd/avx2.rs206
-rw-r--r--vendor/httparse/src/simd/mod.rs153
-rw-r--r--vendor/httparse/src/simd/neon.rs258
-rw-r--r--vendor/httparse/src/simd/runtime.rs57
-rw-r--r--vendor/httparse/src/simd/sse42.rs142
-rw-r--r--vendor/httparse/src/simd/swar.rs235
-rw-r--r--vendor/httparse/tests/uri.rs3692
19 files changed, 0 insertions, 9214 deletions
diff --git a/vendor/httparse/.cargo-checksum.json b/vendor/httparse/.cargo-checksum.json
deleted file mode 100644
index 3495ea67..00000000
--- a/vendor/httparse/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.lock":"ec51aecd295189c21ca216e1bb6e1f04e9f45d7dfc62da5c00480aebbf87a515","Cargo.toml":"067da5f6334526ce5f080909e5c271dd0968ab4198a65eea51d93b242febb48a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"391a5396cec6230bfabd4ef4eb2350eb895bc5efce377a2218f5702ed020d3e3","README.md":"eb23916ad2e4e904ee31e2af02e71ffd8f2d0c97f9e529f3e02f300a120e2c8b","benches/parse.rs":"1c76d3831410e0c2da0cbbee43431c2d28e2f1969664dea2a6a0e81f0a1c88be","build.rs":"eba8e341d746a6cf54249c62afe9eb237e7c21fcf9937223e894549e3a34d489","clippy.toml":"fd62dce2727b03fd4a8f6f3241e9da1e24ac2ff053d3986b0576c140823ec1ea","src/iter.rs":"630132d2d6fafa80c126b7b20b097c5ac7215575f7b61c8f8d7101b58ca57d0a","src/lib.rs":"a8307ce632f27b095cb84de27cfd8fc237977075d3eed41041f463c6afd9b757","src/macros.rs":"4e152282a120ec322f0873c65d2c334d7161f0085e91c52d45793c87f83e3e5c","src/simd/avx2.rs":"ce35db9ab9783880f44786a9d65727b0c5862a957d845e9f3d8a358b3ca4b01a","src/simd/mod.rs":"4fe941717937542c4c88eb95ffefb26db8492e4b5a1d46696fce0b5329702a21","src/simd/neon.rs":"fed66a5d37873dbf901ad2b69e9d08711c570a4a5fc958e13539808501ec9ac3","src/simd/runtime.rs":"fec921120b04042d9c3dbc78ced3477e112f16e4d06be68ac8d50ddce54b8da7","src/simd/sse42.rs":"04c1c6f29375eb87d0e7712deadd9ba3c94d20525b67ff869a266cc6b75cedf6","src/simd/swar.rs":"24d15cfaa7b1ac8f2a5ff74a590eb0e9f0c87de6058c2c65919e33f9f1923080","tests/uri.rs":"62664aa2db82b2b24174ef74b7b00b675806608bfcb64763f97b639b62dd3701"},"package":"6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"} \ No newline at end of file
diff --git a/vendor/httparse/Cargo.lock b/vendor/httparse/Cargo.lock
deleted file mode 100644
index e898732e..00000000
--- a/vendor/httparse/Cargo.lock
+++ /dev/null
@@ -1,688 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "autocfg"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
-
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bstr"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
-dependencies = [
- "lazy_static",
- "memchr",
- "regex-automata",
- "serde",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
-
-[[package]]
-name = "byteorder"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
-
-[[package]]
-name = "cast"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "clap"
-version = "2.34.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
-dependencies = [
- "bitflags",
- "textwrap",
- "unicode-width",
-]
-
-[[package]]
-name = "criterion"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f"
-dependencies = [
- "atty",
- "cast",
- "clap",
- "criterion-plot",
- "csv",
- "itertools",
- "lazy_static",
- "num-traits",
- "oorandom",
- "plotters",
- "rayon",
- "regex",
- "serde",
- "serde_cbor",
- "serde_derive",
- "serde_json",
- "tinytemplate",
- "walkdir",
-]
-
-[[package]]
-name = "criterion-plot"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876"
-dependencies = [
- "cast",
- "itertools",
-]
-
-[[package]]
-name = "crossbeam-channel"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
-dependencies = [
- "cfg-if",
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-deque"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
-dependencies = [
- "cfg-if",
- "crossbeam-epoch",
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-epoch"
-version = "0.9.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
-dependencies = [
- "autocfg",
- "cfg-if",
- "crossbeam-utils",
- "memoffset",
- "once_cell",
- "scopeguard",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.8.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
-dependencies = [
- "cfg-if",
- "once_cell",
-]
-
-[[package]]
-name = "csv"
-version = "1.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
-dependencies = [
- "bstr",
- "csv-core",
- "itoa 0.4.8",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "csv-core"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "either"
-version = "1.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
-
-[[package]]
-name = "getrandom"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "half"
-version = "1.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "httparse"
-version = "1.10.1"
-dependencies = [
- "criterion",
- "rand",
-]
-
-[[package]]
-name = "itertools"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itoa"
-version = "0.4.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
-
-[[package]]
-name = "itoa"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
-
-[[package]]
-name = "js-sys"
-version = "0.3.59"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2"
-dependencies = [
- "wasm-bindgen",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
-name = "libc"
-version = "0.2.169"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
-
-[[package]]
-name = "log"
-version = "0.4.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "memchr"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
-
-[[package]]
-name = "memoffset"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "num-traits"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "num_cpus"
-version = "1.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
-
-[[package]]
-name = "oorandom"
-version = "11.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
-
-[[package]]
-name = "plotters"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9428003b84df1496fb9d6eeee9c5f8145cb41ca375eb0dad204328888832811f"
-dependencies = [
- "num-traits",
- "plotters-backend",
- "plotters-svg",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "plotters-backend"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142"
-
-[[package]]
-name = "plotters-svg"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0918736323d1baff32ee0eade54984f6f201ad7e97d5cfb5d6ab4a358529615"
-dependencies = [
- "plotters-backend",
-]
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
-dependencies = [
- "zerocopy",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.93"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.38"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "rayon"
-version = "1.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
-dependencies = [
- "autocfg",
- "crossbeam-deque",
- "either",
- "rayon-core",
-]
-
-[[package]]
-name = "rayon-core"
-version = "1.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
-dependencies = [
- "crossbeam-channel",
- "crossbeam-deque",
- "crossbeam-utils",
- "num_cpus",
-]
-
-[[package]]
-name = "regex"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
-dependencies = [
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
-
-[[package]]
-name = "ryu"
-version = "1.0.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
-
-[[package]]
-name = "same-file"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "scopeguard"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
-
-[[package]]
-name = "serde"
-version = "1.0.140"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
-
-[[package]]
-name = "serde_cbor"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
-dependencies = [
- "half",
- "serde",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.140"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.98",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.82"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7"
-dependencies = [
- "itoa 1.0.2",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "syn"
-version = "1.0.98"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
-version = "2.0.96"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "textwrap"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-dependencies = [
- "unicode-width",
-]
-
-[[package]]
-name = "tinytemplate"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
-dependencies = [
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
-
-[[package]]
-name = "unicode-width"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
-
-[[package]]
-name = "walkdir"
-version = "2.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
-dependencies = [
- "same-file",
- "winapi",
- "winapi-util",
-]
-
-[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.82"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.82"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f"
-dependencies = [
- "bumpalo",
- "log",
- "once_cell",
- "proc-macro2",
- "quote",
- "syn 1.0.98",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.82"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.82"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.98",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.82"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a"
-
-[[package]]
-name = "web-sys"
-version = "0.3.59"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "zerocopy"
-version = "0.7.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
-dependencies = [
- "byteorder",
- "zerocopy-derive",
-]
-
-[[package]]
-name = "zerocopy-derive"
-version = "0.7.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.96",
-]
diff --git a/vendor/httparse/Cargo.toml b/vendor/httparse/Cargo.toml
deleted file mode 100644
index 6b7abb2c..00000000
--- a/vendor/httparse/Cargo.toml
+++ /dev/null
@@ -1,77 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
-#
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
-
-[package]
-edition = "2018"
-name = "httparse"
-version = "1.10.1"
-authors = ["Sean McArthur <sean@seanmonstar.com>"]
-build = "build.rs"
-autolib = false
-autobins = false
-autoexamples = false
-autotests = false
-autobenches = false
-description = "A tiny, safe, speedy, zero-copy HTTP/1.x parser."
-documentation = "https://docs.rs/httparse"
-readme = "README.md"
-keywords = [
- "http",
- "parser",
- "no_std",
-]
-categories = [
- "network-programming",
- "no-std",
- "parser-implementations",
- "web-programming",
-]
-license = "MIT OR Apache-2.0"
-repository = "https://github.com/seanmonstar/httparse"
-
-[features]
-default = ["std"]
-std = []
-
-[lib]
-name = "httparse"
-path = "src/lib.rs"
-bench = false
-
-[[test]]
-name = "uri"
-path = "tests/uri.rs"
-
-[[bench]]
-name = "parse"
-path = "benches/parse.rs"
-harness = false
-
-[dev-dependencies.criterion]
-version = "0.3.5"
-
-[dev-dependencies.rand]
-version = "0.8.5"
-
-[lints.rust.unexpected_cfgs]
-level = "warn"
-priority = 0
-check-cfg = [
- "cfg(httparse_simd)",
- "cfg(httparse_simd_target_feature_avx2)",
- "cfg(httparse_simd_target_feature_sse42)",
- "cfg(httparse_simd_neon_intrinsics)",
-]
-
-[profile.bench]
-opt-level = 3
-lto = true
-codegen-units = 1
diff --git a/vendor/httparse/LICENSE-APACHE b/vendor/httparse/LICENSE-APACHE
deleted file mode 100644
index 16fe87b0..00000000
--- a/vendor/httparse/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/vendor/httparse/LICENSE-MIT b/vendor/httparse/LICENSE-MIT
deleted file mode 100644
index 5e854c5f..00000000
--- a/vendor/httparse/LICENSE-MIT
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2015-2025 Sean McArthur
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
diff --git a/vendor/httparse/README.md b/vendor/httparse/README.md
deleted file mode 100644
index ce79aa60..00000000
--- a/vendor/httparse/README.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# httparse
-
-[![crates.io](https://img.shields.io/crates/v/httparse.svg)](https://crates.io/crates/httparse)
-[![Released API docs](https://docs.rs/httparse/badge.svg)](https://docs.rs/httparse)
-[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE-MIT)
-[![CI](https://github.com/seanmonstar/httparse/workflows/CI/badge.svg)](https://github.com/seanmonstar/httparse/actions?query=workflow%3ACI)
-[![Discord chat][discord-badge]][discord-url]
-
-A push parser for the HTTP 1.x protocol. Avoids allocations. No copy. **Fast.**
-
-Works with `no_std`, simply disable the `std` Cargo feature.
-
-[Changelog](https://github.com/seanmonstar/httparse/releases)
-
-
-[discord-badge]: https://img.shields.io/discord/500028886025895936.svg?logo=discord
-[discord-url]: https://discord.gg/kkwpueZ
-
-## Usage
-
-```rust
-let mut headers = [httparse::EMPTY_HEADER; 64];
-let mut req = httparse::Request::new(&mut headers);
-
-let buf = b"GET /index.html HTTP/1.1\r\nHost";
-assert!(req.parse(buf)?.is_partial());
-
-// a partial request, so we try again once we have more data
-
-let buf = b"GET /index.html HTTP/1.1\r\nHost: example.domain\r\n\r\n";
-assert!(req.parse(buf)?.is_complete());
-```
-
-## License
-
-Licensed under either of
-
-- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or https://apache.org/licenses/LICENSE-2.0)
-- MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
-
-### Contribution
-
-Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
diff --git a/vendor/httparse/benches/parse.rs b/vendor/httparse/benches/parse.rs
deleted file mode 100644
index 7794d31d..00000000
--- a/vendor/httparse/benches/parse.rs
+++ /dev/null
@@ -1,242 +0,0 @@
-use std::time::Duration;
-
-use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput, BatchSize};
-
-const REQ_SHORT: &[u8] = b"\
-GET / HTTP/1.0\r\n\
-Host: example.com\r\n\
-Cookie: session=60; user_id=1\r\n\r\n";
-
-const REQ: &[u8] = b"\
-GET /wp-content/uploads/2010/03/hello-kitty-darth-vader-pink.jpg HTTP/1.1\r\n\
-Host: www.kittyhell.com\r\n\
-User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 Pathtraq/0.9\r\n\
-Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n\
-Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n\
-Accept-Encoding: gzip,deflate\r\n\
-Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n\
-Keep-Alive: 115\r\n\
-Connection: keep-alive\r\n\
-Cookie: wp_ozh_wsa_visits=2; wp_ozh_wsa_visit_lasttime=xxxxxxxxxx; __utma=xxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.x; __utmz=xxxxxxxxx.xxxxxxxxxx.x.x.utmccn=(referral)|utmcsr=reader.livedoor.com|utmcct=/reader/|utmcmd=referral|padding=under256\r\n\r\n";
-
-fn req(c: &mut Criterion) {
- c.benchmark_group("req")
- .throughput(Throughput::Bytes(REQ.len() as u64))
- .bench_function("req", |b| b.iter_batched_ref(|| {
- [httparse::Header {
- name: "",
- value: &[],
- }; 16]
- },|headers| {
- let mut req = httparse::Request::new(headers);
- assert_eq!(
- black_box(req.parse(REQ).unwrap()),
- httparse::Status::Complete(REQ.len())
- );
- }, BatchSize::SmallInput));
-}
-
-fn req_short(c: &mut Criterion) {
- c.benchmark_group("req_short")
- .throughput(Throughput::Bytes(REQ_SHORT.len() as u64))
- .bench_function("req_short", |b| b.iter_batched_ref(|| {
- [httparse::Header {
- name: "",
- value: &[],
- }; 16]
- },|headers| {
- let mut req = httparse::Request::new(headers);
- assert_eq!(
- req.parse(black_box(REQ_SHORT)).unwrap(),
- httparse::Status::Complete(REQ_SHORT.len())
- );
- }, BatchSize::SmallInput));
-}
-
-const RESP_SHORT: &[u8] = b"\
-HTTP/1.0 200 OK\r\n\
-Date: Wed, 21 Oct 2015 07:28:00 GMT\r\n\
-Set-Cookie: session=60; user_id=1\r\n\r\n";
-
-// These particular headers don't all make semantic sense for a response, but they're syntactically valid.
-const RESP: &[u8] = b"\
-HTTP/1.1 200 OK\r\n\
-Date: Wed, 21 Oct 2015 07:28:00 GMT\r\n\
-Host: www.kittyhell.com\r\n\
-User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 Pathtraq/0.9\r\n\
-Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n\
-Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n\
-Accept-Encoding: gzip,deflate\r\n\
-Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n\
-Keep-Alive: 115\r\n\
-Connection: keep-alive\r\n\
-Cookie: wp_ozh_wsa_visits=2; wp_ozh_wsa_visit_lasttime=xxxxxxxxxx; __utma=xxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.x; __utmz=xxxxxxxxx.xxxxxxxxxx.x.x.utmccn=(referral)|utmcsr=reader.livedoor.com|utmcct=/reader/|utmcmd=referral|padding=under256\r\n\r\n";
-
-fn resp(c: &mut Criterion) {
- c.benchmark_group("resp")
- .throughput(Throughput::Bytes(RESP.len() as u64))
- .bench_function("resp", |b| b.iter_batched_ref(|| {
- [httparse::Header {
- name: "",
- value: &[],
- }; 16]
- }, |headers| {
- let mut resp = httparse::Response::new(headers);
- assert_eq!(
- resp.parse(black_box(RESP)).unwrap(),
- httparse::Status::Complete(RESP.len())
- );
- }, BatchSize::SmallInput));
-}
-
-fn resp_short(c: &mut Criterion) {
- c.benchmark_group("resp_short")
- .throughput(Throughput::Bytes(RESP_SHORT.len() as u64))
- .bench_function("resp_short", |b| b.iter_batched_ref(|| {
- [httparse::Header {
- name: "",
- value: &[],
- }; 16]
- },
- |headers| {
- let mut resp = httparse::Response::new(headers);
- assert_eq!(
- resp.parse(black_box(RESP_SHORT)).unwrap(),
- httparse::Status::Complete(RESP_SHORT.len())
- );
- }, BatchSize::SmallInput));
-}
-
-fn uri(c: &mut Criterion) {
- fn _uri(c: &mut Criterion, name: &str, input: &'static [u8]) {
- c.benchmark_group("uri")
- .throughput(Throughput::Bytes(input.len() as u64))
- .bench_function(name, |b| b.iter(|| {
- let mut b = httparse::_benchable::Bytes::new(black_box(input));
- httparse::_benchable::parse_uri(&mut b).unwrap()
- }));
- }
-
- const S: &[u8] = b" ";
- const CHUNK64: &[u8] = b"/wp-content/uploads/2022/08/31/hello-kitty-darth-vader-pink.webp";
- let chunk_4k = CHUNK64.repeat(64);
-
- // 1b to 4096b
- for p in 0..=12 {
- let n = 1 << p;
- _uri(c, &format!("uri_{:04}b", n), [chunk_4k[..n].to_vec(), S.into()].concat().leak());
- }
-}
-
-fn header(c: &mut Criterion) {
- fn _header(c: &mut Criterion, name: &str, input: &'static [u8]) {
- c.benchmark_group("header")
- .throughput(Throughput::Bytes(input.len() as u64))
- .bench_function(name, |b| b.iter_batched_ref(|| [httparse::EMPTY_HEADER; 128],|headers| {
- let status = httparse::parse_headers(black_box(input), headers).unwrap();
- black_box(status.unwrap()).0
- }, BatchSize::SmallInput));
- }
-
- const RN: &[u8] = b"\r\n";
- const RNRN: &[u8] = b"\r\n\r\n";
- const TINY_RN: &[u8] = b"a: b\r\n"; // minimal header line
- const XFOOBAR: &[u8] = b"X-Foobar";
- let xfoobar_4k = XFOOBAR.repeat(4096/XFOOBAR.len());
-
- // header names 1b to 4096b
- for p in 0..=12 {
- let n = 1 << p;
- let payload = [&xfoobar_4k[..n], b": b", RNRN].concat().leak();
- _header(c, &format!("name_{:04}b", n), payload);
- }
-
- // header values 1b to 4096b
- for p in 0..=12 {
- let n = 1 << p;
- let payload = [b"a: ", &xfoobar_4k[..n], RNRN].concat().leak();
- _header(c, &format!("value_{:04}b", n), payload);
- }
-
- // 1 to 128
- for p in 0..=7 {
- let n = 1 << p;
- _header(c, &format!("count_{:03}", n), [TINY_RN.repeat(n), RN.into()].concat().leak());
- }
-}
-
-fn version(c: &mut Criterion) {
- fn _version(c: &mut Criterion, name: &str, input: &'static [u8]) {
- c.benchmark_group("version")
- .throughput(Throughput::Bytes(input.len() as u64))
- .bench_function(name, |b| b.iter(|| {
- let mut b = httparse::_benchable::Bytes::new(black_box(input));
- httparse::_benchable::parse_version(&mut b).unwrap()
- }));
- }
-
- _version(c, "http10", b"HTTP/1.0\r\n");
- _version(c, "http11", b"HTTP/1.1\r\n");
- _version(c, "partial", b"HTTP/1.");
-}
-
-fn method(c: &mut Criterion) {
- fn _method(c: &mut Criterion, name: &str, input: &[u8]) {
- c.benchmark_group("method")
- .throughput(Throughput::Bytes(input.len() as u64))
- .bench_function(name, |b| b.iter(|| {
- let mut b = httparse::_benchable::Bytes::new(black_box(input));
- httparse::_benchable::parse_method(&mut b).unwrap()
- }));
- }
-
- // Common methods should be fast-pathed
- const COMMON_METHODS: &[&str] = &["GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", "PATCH"];
- for method in COMMON_METHODS {
- _method(c, &method.to_lowercase(), format!("{} / HTTP/1.1\r\n", method).as_bytes());
- }
- // Custom methods should be infrequent and thus not worth optimizing
- _method(c, "custom", b"CUSTOM / HTTP/1.1\r\n");
- _method(c, "w3!rd", b"w3!rd / HTTP/1.1\r\n");
-}
-
-fn many_requests(c: &mut Criterion) {
- use rand::{rngs::StdRng, seq::SliceRandom, SeedableRng};
- let mut requests = [
- ("GET", 500),
- ("POST", 300),
- ("OPTIONS", 100),
- ("HEAD", 50),
- ("w3!r`d", 20),
- ]
- .iter()
- .flat_map(|&(method, count)| std::iter::repeat(method).take(count))
- .map(|method| format!("{method} / HTTP/1.1\r\n\r\n"))
- .collect::<Vec<_>>();
- SliceRandom::shuffle(&mut *requests, &mut StdRng::seed_from_u64(0));
-
- let total_bytes: usize = requests.iter().map(String::len).sum();
-
- c.benchmark_group("many_requests")
- .throughput(Throughput::Bytes(total_bytes as u64))
- .measurement_time(Duration::from_secs(1))
- .sample_size(1000)
- .bench_function("_", |b| {
- b.iter(|| {
- requests.iter().for_each(|req| {
- let mut b = httparse::_benchable::Bytes::new(black_box(req.as_bytes()));
- httparse::_benchable::parse_method(&mut b).unwrap();
- });
- })
- });
-}
-
-const WARMUP: Duration = Duration::from_millis(100);
-const MTIME: Duration = Duration::from_millis(100);
-const SAMPLES: usize = 200;
-criterion_group!{
- name = benches;
- config = Criterion::default().sample_size(SAMPLES).warm_up_time(WARMUP).measurement_time(MTIME);
- targets = req, req_short, resp, resp_short, uri, header, version, method, many_requests
-}
-criterion_main!(benches);
diff --git a/vendor/httparse/build.rs b/vendor/httparse/build.rs
deleted file mode 100644
index bffcedb6..00000000
--- a/vendor/httparse/build.rs
+++ /dev/null
@@ -1,133 +0,0 @@
-use std::env;
-use std::ffi::OsString;
-use std::process::Command;
-
-fn main() {
- // We check rustc version to enable features beyond MSRV, such as:
- // - 1.59 => neon_intrinsics
- let rustc = env::var_os("RUSTC").unwrap_or(OsString::from("rustc"));
- let output = Command::new(rustc)
- .arg("--version")
- .output()
- .expect("failed to check 'rustc --version'")
- .stdout;
-
- let raw_version = String::from_utf8(output)
- .expect("rustc version output should be utf-8");
-
- let version = match Version::parse(&raw_version) {
- Ok(version) => version,
- Err(err) => {
- println!("cargo:warning=failed to parse `rustc --version`: {}", err);
- return;
- }
- };
-
- enable_new_features(version);
-}
-
-fn enable_new_features(version: Version) {
- enable_simd(version);
-}
-
-fn enable_simd(version: Version) {
- if env::var_os("CARGO_FEATURE_STD").is_none() {
- println!("cargo:warning=building for no_std disables httparse SIMD");
- return;
- }
- if env::var_os("CARGO_CFG_MIRI").is_some() {
- println!("cargo:warning=building for Miri disables httparse SIMD");
- return;
- }
-
- let env_disable = "CARGO_CFG_HTTPARSE_DISABLE_SIMD";
- if var_is(env_disable, "1") {
- println!("cargo:warning=detected {} environment variable, disabling SIMD", env_disable);
- return;
- }
-
- // 1.59.0 is the first version to support neon_intrinsics
- if version >= Version(1, 59, 0) {
- println!("cargo:rustc-cfg=httparse_simd_neon_intrinsics");
- }
-
- println!("cargo:rustc-cfg=httparse_simd");
-
- // cfg(target_feature) isn't stable yet, but CARGO_CFG_TARGET_FEATURE has
- // a list... We aren't doing anything unsafe, since the is_x86_feature_detected
- // macro still checks in the actual lib, BUT!
- //
- // By peeking at the list here, we can change up slightly how we do feature
- // detection in the lib. If our features aren't in the feature list, we
- // stick with a cached runtime detection strategy.
- //
- // But if the features *are* in the list, we benefit from removing our cache,
- // since the compiler will eliminate several branches with its internal
- // cfg(target_feature) usage.
-
-
- let env_runtime_only = "CARGO_CFG_HTTPARSE_DISABLE_SIMD_COMPILETIME";
- if var_is(env_runtime_only, "1") {
- println!("cargo:warning=detected {} environment variable, using runtime SIMD detection only", env_runtime_only);
- return;
- }
- let feature_list = match env::var_os("CARGO_CFG_TARGET_FEATURE") {
- Some(var) => match var.into_string() {
- Ok(s) => s,
- Err(_) => {
- println!("cargo:warning=CARGO_CFG_TARGET_FEATURE was not valid utf-8");
- return;
- },
- },
- None => {
- println!("cargo:warning=CARGO_CFG_TARGET_FEATURE was not set");
- return
- },
- };
-
- let features = feature_list.split(',').map(|s| s.trim());
- if features.clone().any(|f| f == "sse4.2") {
- println!("cargo:rustc-cfg=httparse_simd_target_feature_sse42");
- }
- if features.clone().any(|f| f == "avx2") {
- println!("cargo:rustc-cfg=httparse_simd_target_feature_avx2");
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
-struct Version (u32, u32, u32);
-
-impl Version {
- fn parse(s: &str) -> Result<Version, String> {
- if !s.starts_with("rustc ") {
- return Err(format!("unrecognized version string: {}", s));
- }
- let s = s.trim_start_matches("rustc ");
-
- let mut iter = s
- .split('.')
- .take(3)
- .map(|s| match s.find(|c: char| !c.is_ascii_digit()) {
- Some(end) => &s[..end],
- None => s,
- })
- .map(|s| s.parse::<u32>().map_err(|e| e.to_string()));
-
- if iter.clone().count() != 3 {
- return Err(format!("not enough version parts: {:?}", s));
- }
-
- let major = iter.next().unwrap()?;
- let minor = iter.next().unwrap()?;
- let patch = iter.next().unwrap()?;
-
- Ok(Version(major, minor, patch))
- }
-}
-
-fn var_is(key: &str, val: &str) -> bool {
- match env::var(key) {
- Ok(v) => v == val,
- Err(_) => false,
- }
-}
diff --git a/vendor/httparse/clippy.toml b/vendor/httparse/clippy.toml
deleted file mode 100644
index 7846a3e0..00000000
--- a/vendor/httparse/clippy.toml
+++ /dev/null
@@ -1 +0,0 @@
-msrv = "1.47"
diff --git a/vendor/httparse/src/iter.rs b/vendor/httparse/src/iter.rs
deleted file mode 100644
index 98c1d7bc..00000000
--- a/vendor/httparse/src/iter.rs
+++ /dev/null
@@ -1,199 +0,0 @@
-use core::convert::TryFrom;
-use core::convert::TryInto;
-
-#[allow(missing_docs)]
-pub struct Bytes<'a> {
- start: *const u8,
- end: *const u8,
- /// INVARIANT: start <= cursor && cursor <= end
- cursor: *const u8,
- phantom: core::marker::PhantomData<&'a ()>,
-}
-
-#[allow(missing_docs)]
-impl<'a> Bytes<'a> {
- #[inline]
- pub fn new(slice: &'a [u8]) -> Bytes<'a> {
- let start = slice.as_ptr();
- // SAFETY: obtain pointer to slice end; start points to slice start.
- let end = unsafe { start.add(slice.len()) };
- let cursor = start;
- Bytes {
- start,
- end,
- cursor,
- phantom: core::marker::PhantomData,
- }
- }
-
- #[inline]
- pub fn pos(&self) -> usize {
- self.cursor as usize - self.start as usize
- }
-
- #[inline]
- pub fn peek(&self) -> Option<u8> {
- if self.cursor < self.end {
- // SAFETY: bounds checked
- Some(unsafe { *self.cursor })
- } else {
- None
- }
- }
-
- /// Peek at byte `n` ahead of cursor
- ///
- /// # Safety
- ///
- /// Caller must ensure that `n <= self.len()`, otherwise `self.cursor.add(n)` is UB.
- /// That means there are at least `n-1` bytes between `self.cursor` and `self.end`
- /// and `self.cursor.add(n)` is either `self.end` or points to a valid byte.
- #[inline]
- pub unsafe fn peek_ahead(&self, n: usize) -> Option<u8> {
- debug_assert!(n <= self.len());
- // SAFETY: by preconditions
- let p = unsafe { self.cursor.add(n) };
- if p < self.end {
- // SAFETY: by preconditions, if this is not `self.end`,
- // then it is safe to dereference
- Some(unsafe { *p })
- } else {
- None
- }
- }
-
- #[inline]
- pub fn peek_n<'b: 'a, U: TryFrom<&'a [u8]>>(&'b self, n: usize) -> Option<U> {
- // TODO: once we bump MSRC, use const generics to allow only [u8; N] reads
- // TODO: drop `n` arg in favour of const
- // let n = core::mem::size_of::<U>();
- self.as_ref().get(..n)?.try_into().ok()
- }
-
- /// Advance by 1, equivalent to calling `advance(1)`.
- ///
- /// # Safety
- ///
- /// Caller must ensure that Bytes hasn't been advanced/bumped by more than [`Bytes::len()`].
- #[inline]
- pub unsafe fn bump(&mut self) {
- self.advance(1)
- }
-
- /// Advance cursor by `n`
- ///
- /// # Safety
- ///
- /// Caller must ensure that Bytes hasn't been advanced/bumped by more than [`Bytes::len()`].
- #[inline]
- pub unsafe fn advance(&mut self, n: usize) {
- self.cursor = self.cursor.add(n);
- debug_assert!(self.cursor <= self.end, "overflow");
- }
-
- #[inline]
- pub fn len(&self) -> usize {
- self.end as usize - self.cursor as usize
- }
-
- #[inline]
- pub fn is_empty(&self) -> bool {
- self.len() == 0
- }
-
- #[inline]
- pub fn slice(&mut self) -> &'a [u8] {
- // SAFETY: not moving position at all, so it's safe
- let slice = unsafe { slice_from_ptr_range(self.start, self.cursor) };
- self.commit();
- slice
- }
-
- // TODO: this is an anti-pattern, should be removed
- /// Deprecated. Do not use!
- /// # Safety
- ///
- /// Caller must ensure that `skip` is at most the number of advances (i.e., `bytes.advance(3)`
- /// implies a skip of at most 3).
- #[inline]
- pub unsafe fn slice_skip(&mut self, skip: usize) -> &'a [u8] {
- debug_assert!(skip <= self.cursor.offset_from(self.start) as usize);
- let head = slice_from_ptr_range(self.start, self.cursor.sub(skip));
- self.commit();
- head
- }
-
- #[inline]
- pub fn commit(&mut self) {
- self.start = self.cursor
- }
-
- /// # Safety
- ///
- /// see [`Bytes::advance`] safety comment.
- #[inline]
- pub unsafe fn advance_and_commit(&mut self, n: usize) {
- self.advance(n);
- self.commit();
- }
-
- #[inline]
- pub fn as_ptr(&self) -> *const u8 {
- self.cursor
- }
-
- #[inline]
- pub fn start(&self) -> *const u8 {
- self.start
- }
-
- #[inline]
- pub fn end(&self) -> *const u8 {
- self.end
- }
-
- /// # Safety
- ///
- /// Must ensure invariant `bytes.start() <= ptr && ptr <= bytes.end()`.
- #[inline]
- pub unsafe fn set_cursor(&mut self, ptr: *const u8) {
- debug_assert!(ptr >= self.start);
- debug_assert!(ptr <= self.end);
- self.cursor = ptr;
- }
-}
-
-impl AsRef<[u8]> for Bytes<'_> {
- #[inline]
- fn as_ref(&self) -> &[u8] {
- // SAFETY: not moving position at all, so it's safe
- unsafe { slice_from_ptr_range(self.cursor, self.end) }
- }
-}
-
-/// # Safety
-///
-/// Must ensure start and end point to the same memory object to uphold memory safety.
-#[inline]
-unsafe fn slice_from_ptr_range<'a>(start: *const u8, end: *const u8) -> &'a [u8] {
- debug_assert!(start <= end);
- core::slice::from_raw_parts(start, end as usize - start as usize)
-}
-
-impl Iterator for Bytes<'_> {
- type Item = u8;
-
- #[inline]
- fn next(&mut self) -> Option<u8> {
- if self.cursor < self.end {
- // SAFETY: bounds checked dereference
- unsafe {
- let b = *self.cursor;
- self.bump();
- Some(b)
- }
- } else {
- None
- }
- }
-}
diff --git a/vendor/httparse/src/lib.rs b/vendor/httparse/src/lib.rs
deleted file mode 100644
index 06bc4df5..00000000
--- a/vendor/httparse/src/lib.rs
+++ /dev/null
@@ -1,2798 +0,0 @@
-#![cfg_attr(not(feature = "std"), no_std)]
-#![deny(
- missing_docs,
- clippy::missing_safety_doc,
- clippy::undocumented_unsafe_blocks
-)]
-#![cfg_attr(test, deny(warnings))]
-
-//! # httparse
-//!
-//! A push library for parsing HTTP/1.x requests and responses.
-//!
-//! The focus is on speed and safety. Unsafe code is used to keep parsing fast,
-//! but unsafety is contained in a submodule, with invariants enforced. The
-//! parsing internals use an `Iterator` instead of direct indexing, while
-//! skipping bounds checks.
-//!
-//! With Rust 1.27.0 or later, support for SIMD is enabled automatically.
-//! If building an executable to be run on multiple platforms, and thus
-//! not passing `target_feature` or `target_cpu` flags to the compiler,
-//! runtime detection can still detect SSE4.2 or AVX2 support to provide
-//! massive wins.
-//!
-//! If compiling for a specific target, remembering to include
-//! `-C target_cpu=native` allows the detection to become compile time checks,
-//! making it *even* faster.
-
-use core::{fmt, mem, result, str};
-use core::mem::MaybeUninit;
-
-use crate::iter::Bytes;
-
-mod iter;
-#[macro_use] mod macros;
-mod simd;
-
-#[doc(hidden)]
-// Expose some internal functions so we can bench them individually
-// WARNING: Exported for internal benchmarks, not fit for public consumption
-pub mod _benchable {
- pub use super::parse_uri;
- pub use super::parse_version;
- pub use super::parse_method;
- pub use super::iter::Bytes;
-}
-
-/// Determines if byte is a method token char.
-///
-/// > ```notrust
-/// > token = 1*tchar
-/// >
-/// > tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
-/// > / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
-/// > / DIGIT / ALPHA
-/// > ; any VCHAR, except delimiters
-/// > ```
-#[inline]
-fn is_method_token(b: u8) -> bool {
- match b {
- // For the majority case, this can be faster than the table lookup.
- b'A'..=b'Z' => true,
- _ => TOKEN_MAP[b as usize],
- }
-}
-
-// char codes to accept URI string.
-// i.e. b'!' <= char and char != 127
-// TODO: Make a stricter checking for URI string?
-static URI_MAP: [bool; 256] = byte_map!(
- b'!'..=0x7e | 0x80..=0xFF
-);
-
-#[inline]
-pub(crate) fn is_uri_token(b: u8) -> bool {
- URI_MAP[b as usize]
-}
-
-static TOKEN_MAP: [bool; 256] = byte_map!(
- b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' |
- b'!' | b'#' | b'$' | b'%' | b'&' | b'\'' | b'*' | b'+' |
- b'-' | b'.' | b'^' | b'_' | b'`' | b'|' | b'~'
-);
-
-#[inline]
-pub(crate) fn is_header_name_token(b: u8) -> bool {
- TOKEN_MAP[b as usize]
-}
-
-
-static HEADER_VALUE_MAP: [bool; 256] = byte_map!(
- b'\t' | b' '..=0x7e | 0x80..=0xFF
-);
-
-
-#[inline]
-pub(crate) fn is_header_value_token(b: u8) -> bool {
- HEADER_VALUE_MAP[b as usize]
-}
-
-/// An error in parsing.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum Error {
- /// Invalid byte in header name.
- HeaderName,
- /// Invalid byte in header value.
- HeaderValue,
- /// Invalid byte in new line.
- NewLine,
- /// Invalid byte in Response status.
- Status,
- /// Invalid byte where token is required.
- Token,
- /// Parsed more headers than provided buffer can contain.
- TooManyHeaders,
- /// Invalid byte in HTTP version.
- Version,
-}
-
-impl Error {
- #[inline]
- fn description_str(&self) -> &'static str {
- match *self {
- Error::HeaderName => "invalid header name",
- Error::HeaderValue => "invalid header value",
- Error::NewLine => "invalid new line",
- Error::Status => "invalid response status",
- Error::Token => "invalid token",
- Error::TooManyHeaders => "too many headers",
- Error::Version => "invalid HTTP version",
- }
- }
-}
-
-impl fmt::Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(self.description_str())
- }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for Error {
- fn description(&self) -> &str {
- self.description_str()
- }
-}
-
-/// An error in parsing a chunk size.
-// Note: Move this into the error enum once v2.0 is released.
-#[derive(Debug, PartialEq, Eq)]
-pub struct InvalidChunkSize;
-
-impl fmt::Display for InvalidChunkSize {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str("invalid chunk size")
- }
-}
-
-/// A Result of any parsing action.
-///
-/// If the input is invalid, an `Error` will be returned. Note that incomplete
-/// data is not considered invalid, and so will not return an error, but rather
-/// a `Ok(Status::Partial)`.
-pub type Result<T> = result::Result<Status<T>, Error>;
-
-/// The result of a successful parse pass.
-///
-/// `Complete` is used when the buffer contained the complete value.
-/// `Partial` is used when parsing did not reach the end of the expected value,
-/// but no invalid data was found.
-#[derive(Copy, Clone, Eq, PartialEq, Debug)]
-pub enum Status<T> {
- /// The completed result.
- Complete(T),
- /// A partial result.
- Partial
-}
-
-impl<T> Status<T> {
- /// Convenience method to check if status is complete.
- #[inline]
- pub fn is_complete(&self) -> bool {
- match *self {
- Status::Complete(..) => true,
- Status::Partial => false
- }
- }
-
- /// Convenience method to check if status is partial.
- #[inline]
- pub fn is_partial(&self) -> bool {
- match *self {
- Status::Complete(..) => false,
- Status::Partial => true
- }
- }
-
- /// Convenience method to unwrap a Complete value. Panics if the status is
- /// `Partial`.
- #[inline]
- pub fn unwrap(self) -> T {
- match self {
- Status::Complete(t) => t,
- Status::Partial => panic!("Tried to unwrap Status::Partial")
- }
- }
-}
-
-/// Parser configuration.
-#[derive(Clone, Debug, Default)]
-pub struct ParserConfig {
- allow_spaces_after_header_name_in_responses: bool,
- allow_obsolete_multiline_headers_in_responses: bool,
- allow_multiple_spaces_in_request_line_delimiters: bool,
- allow_multiple_spaces_in_response_status_delimiters: bool,
- allow_space_before_first_header_name: bool,
- ignore_invalid_headers_in_responses: bool,
- ignore_invalid_headers_in_requests: bool,
-}
-
-impl ParserConfig {
- /// Sets whether spaces and tabs should be allowed after header names in responses.
- pub fn allow_spaces_after_header_name_in_responses(
- &mut self,
- value: bool,
- ) -> &mut Self {
- self.allow_spaces_after_header_name_in_responses = value;
- self
- }
-
- /// Sets whether multiple spaces are allowed as delimiters in request lines.
- ///
- /// # Background
- ///
- /// The [latest version of the HTTP/1.1 spec][spec] allows implementations to parse multiple
- /// whitespace characters in place of the `SP` delimiters in the request line, including:
- ///
- /// > SP, HTAB, VT (%x0B), FF (%x0C), or bare CR
- ///
- /// This option relaxes the parser to allow for multiple spaces, but does *not* allow the
- /// request line to contain the other mentioned whitespace characters.
- ///
- /// [spec]: https://httpwg.org/http-core/draft-ietf-httpbis-messaging-latest.html#rfc.section.3.p.3
- pub fn allow_multiple_spaces_in_request_line_delimiters(&mut self, value: bool) -> &mut Self {
- self.allow_multiple_spaces_in_request_line_delimiters = value;
- self
- }
-
- /// Whether multiple spaces are allowed as delimiters in request lines.
- pub fn multiple_spaces_in_request_line_delimiters_are_allowed(&self) -> bool {
- self.allow_multiple_spaces_in_request_line_delimiters
- }
-
- /// Sets whether multiple spaces are allowed as delimiters in response status lines.
- ///
- /// # Background
- ///
- /// The [latest version of the HTTP/1.1 spec][spec] allows implementations to parse multiple
- /// whitespace characters in place of the `SP` delimiters in the response status line,
- /// including:
- ///
- /// > SP, HTAB, VT (%x0B), FF (%x0C), or bare CR
- ///
- /// This option relaxes the parser to allow for multiple spaces, but does *not* allow the status
- /// line to contain the other mentioned whitespace characters.
- ///
- /// [spec]: https://httpwg.org/http-core/draft-ietf-httpbis-messaging-latest.html#rfc.section.4.p.3
- pub fn allow_multiple_spaces_in_response_status_delimiters(&mut self, value: bool) -> &mut Self {
- self.allow_multiple_spaces_in_response_status_delimiters = value;
- self
- }
-
- /// Whether multiple spaces are allowed as delimiters in response status lines.
- pub fn multiple_spaces_in_response_status_delimiters_are_allowed(&self) -> bool {
- self.allow_multiple_spaces_in_response_status_delimiters
- }
-
- /// Sets whether obsolete multiline headers should be allowed.
- ///
- /// This is an obsolete part of HTTP/1. Use at your own risk. If you are
- /// building an HTTP library, the newlines (`\r` and `\n`) should be
- /// replaced by spaces before handing the header value to the user.
- ///
- /// # Example
- ///
- /// ```rust
- /// let buf = b"HTTP/1.1 200 OK\r\nFolded-Header: hello\r\n there \r\n\r\n";
- /// let mut headers = [httparse::EMPTY_HEADER; 16];
- /// let mut response = httparse::Response::new(&mut headers);
- ///
- /// let res = httparse::ParserConfig::default()
- /// .allow_obsolete_multiline_headers_in_responses(true)
- /// .parse_response(&mut response, buf);
- ///
- /// assert_eq!(res, Ok(httparse::Status::Complete(buf.len())));
- ///
- /// assert_eq!(response.headers.len(), 1);
- /// assert_eq!(response.headers[0].name, "Folded-Header");
- /// assert_eq!(response.headers[0].value, b"hello\r\n there");
- /// ```
- pub fn allow_obsolete_multiline_headers_in_responses(
- &mut self,
- value: bool,
- ) -> &mut Self {
- self.allow_obsolete_multiline_headers_in_responses = value;
- self
- }
-
- /// Whether obsolete multiline headers should be allowed.
- pub fn obsolete_multiline_headers_in_responses_are_allowed(&self) -> bool {
- self.allow_obsolete_multiline_headers_in_responses
- }
-
- /// Sets whether white space before the first header is allowed
- ///
- /// This is not allowed by spec but some browsers ignore it. So this an option for
- /// compatibility.
- /// See https://github.com/curl/curl/issues/11605 for reference
- /// # Example
- ///
- /// ```rust
- /// let buf = b"HTTP/1.1 200 OK\r\n Space-Before-Header: hello there\r\n\r\n";
- /// let mut headers = [httparse::EMPTY_HEADER; 1];
- /// let mut response = httparse::Response::new(&mut headers[..]);
- /// let result = httparse::ParserConfig::default()
- /// .allow_space_before_first_header_name(true)
- /// .parse_response(&mut response, buf);
- ///
- /// assert_eq!(result, Ok(httparse::Status::Complete(buf.len())));
- /// assert_eq!(response.version.unwrap(), 1);
- /// assert_eq!(response.code.unwrap(), 200);
- /// assert_eq!(response.reason.unwrap(), "OK");
- /// assert_eq!(response.headers.len(), 1);
- /// assert_eq!(response.headers[0].name, "Space-Before-Header");
- /// assert_eq!(response.headers[0].value, &b"hello there"[..]);
- /// ```
- pub fn allow_space_before_first_header_name(&mut self, value: bool) -> &mut Self {
- self.allow_space_before_first_header_name = value;
- self
- }
-
- /// Whether white space before first header is allowed or not
- pub fn space_before_first_header_name_are_allowed(&self) -> bool {
- self.allow_space_before_first_header_name
- }
-
- /// Parses a request with the given config.
- pub fn parse_request<'buf>(
- &self,
- request: &mut Request<'_, 'buf>,
- buf: &'buf [u8],
- ) -> Result<usize> {
- request.parse_with_config(buf, self)
- }
-
- /// Parses a request with the given config and buffer for headers
- pub fn parse_request_with_uninit_headers<'headers, 'buf>(
- &self,
- request: &mut Request<'headers, 'buf>,
- buf: &'buf [u8],
- headers: &'headers mut [MaybeUninit<Header<'buf>>],
- ) -> Result<usize> {
- request.parse_with_config_and_uninit_headers(buf, self, headers)
- }
-
- /// Sets whether invalid header lines should be silently ignored in responses.
- ///
- /// This mimicks the behaviour of major browsers. You probably don't want this.
- /// You should only want this if you are implementing a proxy whose main
- /// purpose is to sit in front of browsers whose users access arbitrary content
- /// which may be malformed, and they expect everything that works without
- /// the proxy to keep working with the proxy.
- ///
- /// This option will prevent `ParserConfig::parse_response` from returning
- /// an error encountered when parsing a header, except if the error was caused
- /// by the character NUL (ASCII code 0), as Chrome specifically always reject
- /// those, or if the error was caused by a lone character `\r`, as Firefox and
- /// Chrome behave differently in that case.
- ///
- /// The ignorable errors are:
- /// * empty header names;
- /// * characters that are not allowed in header names, except for `\0` and `\r`;
- /// * when `allow_spaces_after_header_name_in_responses` is not enabled,
- /// spaces and tabs between the header name and the colon;
- /// * missing colon between header name and value;
- /// * when `allow_obsolete_multiline_headers_in_responses` is not enabled,
- /// headers using obsolete line folding.
- /// * characters that are not allowed in header values except for `\0` and `\r`.
- ///
- /// If an ignorable error is encountered, the parser tries to find the next
- /// line in the input to resume parsing the rest of the headers. As lines
- /// contributing to a header using obsolete line folding always start
- /// with whitespace, those will be ignored too. An error will be emitted
- /// nonetheless if it finds `\0` or a lone `\r` while looking for the
- /// next line.
- pub fn ignore_invalid_headers_in_responses(
- &mut self,
- value: bool,
- ) -> &mut Self {
- self.ignore_invalid_headers_in_responses = value;
- self
- }
-
- /// Sets whether invalid header lines should be silently ignored in requests.
- pub fn ignore_invalid_headers_in_requests(
- &mut self,
- value: bool,
- ) -> &mut Self {
- self.ignore_invalid_headers_in_requests = value;
- self
- }
-
- /// Parses a response with the given config.
- pub fn parse_response<'buf>(
- &self,
- response: &mut Response<'_, 'buf>,
- buf: &'buf [u8],
- ) -> Result<usize> {
- response.parse_with_config(buf, self)
- }
-
- /// Parses a response with the given config and buffer for headers
- pub fn parse_response_with_uninit_headers<'headers, 'buf>(
- &self,
- response: &mut Response<'headers, 'buf>,
- buf: &'buf [u8],
- headers: &'headers mut [MaybeUninit<Header<'buf>>],
- ) -> Result<usize> {
- response.parse_with_config_and_uninit_headers(buf, self, headers)
- }
-}
-
-/// A parsed Request.
-///
-/// The optional values will be `None` if a parse was not complete, and did not
-/// parse the associated property. This allows you to inspect the parts that
-/// could be parsed, before reading more, in case you wish to exit early.
-///
-/// # Example
-///
-/// ```no_run
-/// let buf = b"GET /404 HTTP/1.1\r\nHost:";
-/// let mut headers = [httparse::EMPTY_HEADER; 16];
-/// let mut req = httparse::Request::new(&mut headers);
-/// let res = req.parse(buf).unwrap();
-/// if res.is_partial() {
-/// match req.path {
-/// Some(ref path) => {
-/// // check router for path.
-/// // /404 doesn't exist? we could stop parsing
-/// },
-/// None => {
-/// // must read more and parse again
-/// }
-/// }
-/// }
-/// ```
-#[derive(Debug, Eq, PartialEq)]
-pub struct Request<'headers, 'buf> {
- /// The request method, such as `GET`.
- pub method: Option<&'buf str>,
- /// The request path, such as `/about-us`.
- pub path: Option<&'buf str>,
- /// The request minor version, such as `1` for `HTTP/1.1`.
- pub version: Option<u8>,
- /// The request headers.
- pub headers: &'headers mut [Header<'buf>]
-}
-
-impl<'h, 'b> Request<'h, 'b> {
- /// Creates a new Request, using a slice of headers you allocate.
- #[inline]
- pub fn new(headers: &'h mut [Header<'b>]) -> Request<'h, 'b> {
- Request {
- method: None,
- path: None,
- version: None,
- headers,
- }
- }
-
- fn parse_with_config_and_uninit_headers(
- &mut self,
- buf: &'b [u8],
- config: &ParserConfig,
- mut headers: &'h mut [MaybeUninit<Header<'b>>],
- ) -> Result<usize> {
- let orig_len = buf.len();
- let mut bytes = Bytes::new(buf);
- complete!(skip_empty_lines(&mut bytes));
- let method = complete!(parse_method(&mut bytes));
- self.method = Some(method);
- if config.allow_multiple_spaces_in_request_line_delimiters {
- complete!(skip_spaces(&mut bytes));
- }
- self.path = Some(complete!(parse_uri(&mut bytes)));
- if config.allow_multiple_spaces_in_request_line_delimiters {
- complete!(skip_spaces(&mut bytes));
- }
- self.version = Some(complete!(parse_version(&mut bytes)));
- newline!(bytes);
-
- let len = orig_len - bytes.len();
- let headers_len = complete!(parse_headers_iter_uninit(
- &mut headers,
- &mut bytes,
- &HeaderParserConfig {
- allow_spaces_after_header_name: false,
- allow_obsolete_multiline_headers: false,
- allow_space_before_first_header_name: config.allow_space_before_first_header_name,
- ignore_invalid_headers: config.ignore_invalid_headers_in_requests
- },
- ));
- /* SAFETY: see `parse_headers_iter_uninit` guarantees */
- self.headers = unsafe { assume_init_slice(headers) };
-
- Ok(Status::Complete(len + headers_len))
- }
-
- /// Try to parse a buffer of bytes into the Request,
- /// except use an uninitialized slice of `Header`s.
- ///
- /// For more information, see `parse`
- pub fn parse_with_uninit_headers(
- &mut self,
- buf: &'b [u8],
- headers: &'h mut [MaybeUninit<Header<'b>>],
- ) -> Result<usize> {
- self.parse_with_config_and_uninit_headers(buf, &Default::default(), headers)
- }
-
- fn parse_with_config(&mut self, buf: &'b [u8], config: &ParserConfig) -> Result<usize> {
- let headers = mem::take(&mut self.headers);
-
- /* SAFETY: see `parse_headers_iter_uninit` guarantees */
- unsafe {
- let headers: *mut [Header<'_>] = headers;
- let headers = headers as *mut [MaybeUninit<Header<'_>>];
- match self.parse_with_config_and_uninit_headers(buf, config, &mut *headers) {
- Ok(Status::Complete(idx)) => Ok(Status::Complete(idx)),
- other => {
- // put the original headers back
- self.headers = &mut *(headers as *mut [Header<'_>]);
- other
- },
- }
- }
- }
-
- /// Try to parse a buffer of bytes into the Request.
- ///
- /// Returns byte offset in `buf` to start of HTTP body.
- pub fn parse(&mut self, buf: &'b [u8]) -> Result<usize> {
- self.parse_with_config(buf, &Default::default())
- }
-}
-
-#[inline]
-fn skip_empty_lines(bytes: &mut Bytes<'_>) -> Result<()> {
- loop {
- let b = bytes.peek();
- match b {
- Some(b'\r') => {
- // SAFETY: peeked and found `\r`, so it's safe to bump 1 pos
- unsafe { bytes.bump() };
- expect!(bytes.next() == b'\n' => Err(Error::NewLine));
- }
- Some(b'\n') => {
- // SAFETY: peeked and found `\n`, so it's safe to bump 1 pos
- unsafe {
- bytes.bump();
- }
- }
- Some(..) => {
- bytes.slice();
- return Ok(Status::Complete(()));
- }
- None => return Ok(Status::Partial),
- }
- }
-}
-
-#[inline]
-fn skip_spaces(bytes: &mut Bytes<'_>) -> Result<()> {
- loop {
- let b = bytes.peek();
- match b {
- Some(b' ') => {
- // SAFETY: peeked and found ` `, so it's safe to bump 1 pos
- unsafe { bytes.bump() };
- }
- Some(..) => {
- bytes.slice();
- return Ok(Status::Complete(()));
- }
- None => return Ok(Status::Partial),
- }
- }
-}
-
-/// A parsed Response.
-///
-/// See `Request` docs for explanation of optional values.
-#[derive(Debug, Eq, PartialEq)]
-pub struct Response<'headers, 'buf> {
- /// The response minor version, such as `1` for `HTTP/1.1`.
- pub version: Option<u8>,
- /// The response code, such as `200`.
- pub code: Option<u16>,
- /// The response reason-phrase, such as `OK`.
- ///
- /// Contains an empty string if the reason-phrase was missing or contained invalid characters.
- pub reason: Option<&'buf str>,
- /// The response headers.
- pub headers: &'headers mut [Header<'buf>]
-}
-
-impl<'h, 'b> Response<'h, 'b> {
- /// Creates a new `Response` using a slice of `Header`s you have allocated.
- #[inline]
- pub fn new(headers: &'h mut [Header<'b>]) -> Response<'h, 'b> {
- Response {
- version: None,
- code: None,
- reason: None,
- headers,
- }
- }
-
- /// Try to parse a buffer of bytes into this `Response`.
- pub fn parse(&mut self, buf: &'b [u8]) -> Result<usize> {
- self.parse_with_config(buf, &ParserConfig::default())
- }
-
- fn parse_with_config(&mut self, buf: &'b [u8], config: &ParserConfig) -> Result<usize> {
- let headers = mem::take(&mut self.headers);
-
- // SAFETY: see guarantees of [`parse_headers_iter_uninit`], which leaves no uninitialized
- // headers around. On failure, the original headers are restored.
- unsafe {
- let headers: *mut [Header<'_>] = headers;
- let headers = headers as *mut [MaybeUninit<Header<'_>>];
- match self.parse_with_config_and_uninit_headers(buf, config, &mut *headers) {
- Ok(Status::Complete(idx)) => Ok(Status::Complete(idx)),
- other => {
- // put the original headers back
- self.headers = &mut *(headers as *mut [Header<'_>]);
- other
- },
- }
- }
- }
-
- fn parse_with_config_and_uninit_headers(
- &mut self,
- buf: &'b [u8],
- config: &ParserConfig,
- mut headers: &'h mut [MaybeUninit<Header<'b>>],
- ) -> Result<usize> {
- let orig_len = buf.len();
- let mut bytes = Bytes::new(buf);
-
- complete!(skip_empty_lines(&mut bytes));
- self.version = Some(complete!(parse_version(&mut bytes)));
- space!(bytes or Error::Version);
- if config.allow_multiple_spaces_in_response_status_delimiters {
- complete!(skip_spaces(&mut bytes));
- }
- self.code = Some(complete!(parse_code(&mut bytes)));
-
- // RFC7230 says there must be 'SP' and then reason-phrase, but admits
- // its only for legacy reasons. With the reason-phrase completely
- // optional (and preferred to be omitted) in HTTP2, we'll just
- // handle any response that doesn't include a reason-phrase, because
- // it's more lenient, and we don't care anyways.
- //
- // So, a SP means parse a reason-phrase.
- // A newline means go to headers.
- // Anything else we'll say is a malformed status.
- match next!(bytes) {
- b' ' => {
- if config.allow_multiple_spaces_in_response_status_delimiters {
- complete!(skip_spaces(&mut bytes));
- }
- bytes.slice();
- self.reason = Some(complete!(parse_reason(&mut bytes)));
- },
- b'\r' => {
- expect!(bytes.next() == b'\n' => Err(Error::Status));
- bytes.slice();
- self.reason = Some("");
- },
- b'\n' => {
- bytes.slice();
- self.reason = Some("");
- }
- _ => return Err(Error::Status),
- }
-
-
- let len = orig_len - bytes.len();
- let headers_len = complete!(parse_headers_iter_uninit(
- &mut headers,
- &mut bytes,
- &HeaderParserConfig {
- allow_spaces_after_header_name: config.allow_spaces_after_header_name_in_responses,
- allow_obsolete_multiline_headers: config.allow_obsolete_multiline_headers_in_responses,
- allow_space_before_first_header_name: config.allow_space_before_first_header_name,
- ignore_invalid_headers: config.ignore_invalid_headers_in_responses
- }
- ));
- /* SAFETY: see `parse_headers_iter_uninit` guarantees */
- self.headers = unsafe { assume_init_slice(headers) };
- Ok(Status::Complete(len + headers_len))
- }
-}
-
-/// Represents a parsed header.
-#[derive(Copy, Clone, Eq, PartialEq)]
-pub struct Header<'a> {
- /// The name portion of a header.
- ///
- /// A header name must be valid ASCII-US, so it's safe to store as a `&str`.
- pub name: &'a str,
- /// The value portion of a header.
- ///
- /// While headers **should** be ASCII-US, the specification allows for
- /// values that may not be, and so the value is stored as bytes.
- pub value: &'a [u8],
-}
-
-impl fmt::Debug for Header<'_> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let mut f = f.debug_struct("Header");
- f.field("name", &self.name);
- if let Ok(value) = str::from_utf8(self.value) {
- f.field("value", &value);
- } else {
- f.field("value", &self.value);
- }
- f.finish()
- }
-}
-
-/// An empty header, useful for constructing a `Header` array to pass in for
-/// parsing.
-///
-/// # Example
-///
-/// ```
-/// let headers = [httparse::EMPTY_HEADER; 64];
-/// ```
-pub const EMPTY_HEADER: Header<'static> = Header { name: "", value: b"" };
-
-#[inline]
-#[doc(hidden)]
-#[allow(missing_docs)]
-// WARNING: Exported for internal benchmarks, not fit for public consumption
-pub fn parse_version(bytes: &mut Bytes) -> Result<u8> {
- if let Some(eight) = bytes.peek_n::<[u8; 8]>(8) {
- // NOTE: should be const once MSRV >= 1.44
- let h10: u64 = u64::from_ne_bytes(*b"HTTP/1.0");
- let h11: u64 = u64::from_ne_bytes(*b"HTTP/1.1");
- // SAFETY: peek_n(8) before ensure within bounds
- unsafe {
- bytes.advance(8);
- }
- let block = u64::from_ne_bytes(eight);
- // NOTE: should be match once h10 & h11 are consts
- return if block == h10 {
- Ok(Status::Complete(0))
- } else if block == h11 {
- Ok(Status::Complete(1))
- } else {
- Err(Error::Version)
- };
- }
-
- // else (but not in `else` because of borrow checker)
-
- // If there aren't at least 8 bytes, we still want to detect early
- // if this is a valid version or not. If it is, we'll return Partial.
- expect!(bytes.next() == b'H' => Err(Error::Version));
- expect!(bytes.next() == b'T' => Err(Error::Version));
- expect!(bytes.next() == b'T' => Err(Error::Version));
- expect!(bytes.next() == b'P' => Err(Error::Version));
- expect!(bytes.next() == b'/' => Err(Error::Version));
- expect!(bytes.next() == b'1' => Err(Error::Version));
- expect!(bytes.next() == b'.' => Err(Error::Version));
- Ok(Status::Partial)
-}
-
-#[inline]
-#[doc(hidden)]
-#[allow(missing_docs)]
-// WARNING: Exported for internal benchmarks, not fit for public consumption
-pub fn parse_method<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
- const GET: [u8; 4] = *b"GET ";
- const POST: [u8; 4] = *b"POST";
- match bytes.peek_n::<[u8; 4]>(4) {
- Some(GET) => {
- // SAFETY: we matched "GET " which has 4 bytes and is ASCII
- let method = unsafe {
- bytes.advance(4); // advance cursor past "GET "
- str::from_utf8_unchecked(bytes.slice_skip(1)) // "GET" without space
- };
- Ok(Status::Complete(method))
- }
- // SAFETY:
- // If `bytes.peek_n...` returns a Some([u8; 4]),
- // then we are assured that `bytes` contains at least 4 bytes.
- // Thus `bytes.len() >= 4`,
- // and it is safe to peek at byte 4 with `bytes.peek_ahead(4)`.
- Some(POST) if unsafe { bytes.peek_ahead(4) } == Some(b' ') => {
- // SAFETY: we matched "POST " which has 5 bytes
- let method = unsafe {
- bytes.advance(5); // advance cursor past "POST "
- str::from_utf8_unchecked(bytes.slice_skip(1)) // "POST" without space
- };
- Ok(Status::Complete(method))
- }
- _ => parse_token(bytes),
- }
-}
-
-/// From [RFC 7230](https://tools.ietf.org/html/rfc7230):
-///
-/// > ```notrust
-/// > reason-phrase = *( HTAB / SP / VCHAR / obs-text )
-/// > HTAB = %x09 ; horizontal tab
-/// > VCHAR = %x21-7E ; visible (printing) characters
-/// > obs-text = %x80-FF
-/// > ```
-///
-/// > A.2. Changes from RFC 2616
-/// >
-/// > Non-US-ASCII content in header fields and the reason phrase
-/// > has been obsoleted and made opaque (the TEXT rule was removed).
-#[inline]
-fn parse_reason<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
- let mut seen_obs_text = false;
- loop {
- let b = next!(bytes);
- if b == b'\r' {
- expect!(bytes.next() == b'\n' => Err(Error::Status));
- return Ok(Status::Complete(
- // SAFETY: (1) calling bytes.slice_skip(2) is safe, because at least two next! calls
- // advance the bytes iterator.
- // (2) calling from_utf8_unchecked is safe, because the bytes returned by slice_skip
- // were validated to be allowed US-ASCII chars by the other arms of the if/else or
- // otherwise `seen_obs_text` is true and an empty string is returned instead.
- unsafe {
- let bytes = bytes.slice_skip(2);
- if !seen_obs_text {
- // all bytes up till `i` must have been HTAB / SP / VCHAR
- str::from_utf8_unchecked(bytes)
- } else {
- // obs-text characters were found, so return the fallback empty string
- ""
- }
- },
- ));
- } else if b == b'\n' {
- return Ok(Status::Complete(
- // SAFETY: (1) calling bytes.slice_skip(1) is safe, because at least one next! call
- // advance the bytes iterator.
- // (2) see (2) of safety comment above.
- unsafe {
- let bytes = bytes.slice_skip(1);
- if !seen_obs_text {
- // all bytes up till `i` must have been HTAB / SP / VCHAR
- str::from_utf8_unchecked(bytes)
- } else {
- // obs-text characters were found, so return the fallback empty string
- ""
- }
- },
- ));
- } else if !(b == 0x09 || b == b' ' || (0x21..=0x7E).contains(&b) || b >= 0x80) {
- return Err(Error::Status);
- } else if b >= 0x80 {
- seen_obs_text = true;
- }
- }
-}
-
-#[inline]
-fn parse_token<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
- let b = next!(bytes);
- if !is_method_token(b) {
- // First char must be a token char, it can't be a space which would indicate an empty token.
- return Err(Error::Token);
- }
-
- loop {
- let b = next!(bytes);
- if b == b' ' {
- return Ok(Status::Complete(
- // SAFETY: all bytes up till `i` must have been `is_method_token` and therefore also utf-8.
- unsafe { str::from_utf8_unchecked(bytes.slice_skip(1)) },
- ));
- } else if !is_method_token(b) {
- return Err(Error::Token);
- }
- }
-}
-
-#[inline]
-#[doc(hidden)]
-#[allow(missing_docs)]
-// WARNING: Exported for internal benchmarks, not fit for public consumption
-pub fn parse_uri<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
- let start = bytes.pos();
- simd::match_uri_vectored(bytes);
- let end = bytes.pos();
-
- if next!(bytes) == b' ' {
- // URI must have at least one char
- if end == start {
- return Err(Error::Token);
- }
-
- // SAFETY: all bytes up till `i` must have been `is_token` and therefore also utf-8.
- match str::from_utf8(unsafe { bytes.slice_skip(1) }) {
- Ok(uri) => Ok(Status::Complete(uri)),
- Err(_) => Err(Error::Token),
- }
- } else {
- Err(Error::Token)
- }
-}
-
-#[inline]
-fn parse_code(bytes: &mut Bytes<'_>) -> Result<u16> {
- let hundreds = expect!(bytes.next() == b'0'..=b'9' => Err(Error::Status));
- let tens = expect!(bytes.next() == b'0'..=b'9' => Err(Error::Status));
- let ones = expect!(bytes.next() == b'0'..=b'9' => Err(Error::Status));
-
- Ok(Status::Complete((hundreds - b'0') as u16 * 100 +
- (tens - b'0') as u16 * 10 +
- (ones - b'0') as u16))
-}
-
-/// Parse a buffer of bytes as headers.
-///
-/// The return value, if complete and successful, includes the index of the
-/// buffer that parsing stopped at, and a sliced reference to the parsed
-/// headers. The length of the slice will be equal to the number of properly
-/// parsed headers.
-///
-/// # Example
-///
-/// ```
-/// let buf = b"Host: foo.bar\nAccept: */*\n\nblah blah";
-/// let mut headers = [httparse::EMPTY_HEADER; 4];
-/// assert_eq!(httparse::parse_headers(buf, &mut headers),
-/// Ok(httparse::Status::Complete((27, &[
-/// httparse::Header { name: "Host", value: b"foo.bar" },
-/// httparse::Header { name: "Accept", value: b"*/*" }
-/// ][..]))));
-/// ```
-pub fn parse_headers<'b: 'h, 'h>(
- src: &'b [u8],
- mut dst: &'h mut [Header<'b>],
-) -> Result<(usize, &'h [Header<'b>])> {
- let mut iter = Bytes::new(src);
- let pos = complete!(parse_headers_iter(&mut dst, &mut iter, &HeaderParserConfig::default()));
- Ok(Status::Complete((pos, dst)))
-}
-
-#[inline]
-fn parse_headers_iter<'a>(
- headers: &mut &mut [Header<'a>],
- bytes: &mut Bytes<'a>,
- config: &HeaderParserConfig,
-) -> Result<usize> {
- parse_headers_iter_uninit(
- /* SAFETY: see `parse_headers_iter_uninit` guarantees */
- unsafe { deinit_slice_mut(headers) },
- bytes,
- config,
- )
-}
-
-unsafe fn deinit_slice_mut<'a, 'b, T>(s: &'a mut &'b mut [T]) -> &'a mut &'b mut [MaybeUninit<T>] {
- let s: *mut &mut [T] = s;
- let s = s as *mut &mut [MaybeUninit<T>];
- &mut *s
-}
-unsafe fn assume_init_slice<T>(s: &mut [MaybeUninit<T>]) -> &mut [T] {
- let s: *mut [MaybeUninit<T>] = s;
- let s = s as *mut [T];
- &mut *s
-}
-
-#[derive(Clone, Debug, Default)]
-struct HeaderParserConfig {
- allow_spaces_after_header_name: bool,
- allow_obsolete_multiline_headers: bool,
- allow_space_before_first_header_name: bool,
- ignore_invalid_headers: bool,
-}
-
-/* Function which parsers headers into uninitialized buffer.
- *
- * Guarantees that it doesn't write garbage, so casting
- * &mut &mut [Header] -> &mut &mut [MaybeUninit<Header>]
- * is safe here.
- *
- * Also it promises `headers` get shrunk to number of initialized headers,
- * so casting the other way around after calling this function is safe
- */
-fn parse_headers_iter_uninit<'a>(
- headers: &mut &mut [MaybeUninit<Header<'a>>],
- bytes: &mut Bytes<'a>,
- config: &HeaderParserConfig
-) -> Result<usize> {
-
- /* Flow of this function is pretty complex, especially with macros,
- * so this struct makes sure we shrink `headers` to only parsed ones.
- * Comparing to previous code, this only may introduce some additional
- * instructions in case of early return */
- struct ShrinkOnDrop<'r1, 'r2, 'a> {
- headers: &'r1 mut &'r2 mut [MaybeUninit<Header<'a>>],
- num_headers: usize,
- }
-
- impl Drop for ShrinkOnDrop<'_, '_, '_> {
- fn drop(&mut self) {
- let headers = mem::take(self.headers);
-
- /* SAFETY: num_headers is the number of initialized headers */
- let headers = unsafe { headers.get_unchecked_mut(..self.num_headers) };
-
- *self.headers = headers;
- }
- }
-
- let mut autoshrink = ShrinkOnDrop {
- headers,
- num_headers: 0,
- };
- // Track starting pointer to calculate the number of bytes parsed.
- let start = bytes.as_ref().as_ptr() as usize;
- let mut result = Err(Error::TooManyHeaders);
-
- let mut iter = autoshrink.headers.iter_mut();
-
- macro_rules! maybe_continue_after_obsolete_line_folding {
- ($bytes:ident, $label:lifetime) => {
- if config.allow_obsolete_multiline_headers {
- match $bytes.peek() {
- None => {
- // Next byte may be a space, in which case that header
- // is using obsolete line folding, so we may have more
- // whitespace to skip after colon.
- return Ok(Status::Partial);
- }
- Some(b' ') | Some(b'\t') => {
- // The space will be consumed next iteration.
- continue $label;
- }
- _ => {
- // There is another byte after the end of the line,
- // but it's not whitespace, so it's probably another
- // header or the final line return. This header is thus
- // empty.
- },
- }
- }
- }
- }
-
- 'headers: loop {
- // Return the error `$err` if `ignore_invalid_headers_in_responses`
- // is false, otherwise find the end of the current line and resume
- // parsing on the next one.
- macro_rules! handle_invalid_char {
- ($bytes:ident, $b:ident, $err:ident) => {
- if !config.ignore_invalid_headers {
- return Err(Error::$err);
- }
-
- let mut b = $b;
-
- loop {
- if b == b'\r' {
- expect!(bytes.next() == b'\n' => Err(Error::$err));
- break;
- }
- if b == b'\n' {
- break;
- }
- if b == b'\0' {
- return Err(Error::$err);
- }
- b = next!($bytes);
- }
-
- $bytes.slice();
-
- continue 'headers;
- };
- }
-
- // a newline here means the head is over!
- let b = next!(bytes);
- if b == b'\r' {
- expect!(bytes.next() == b'\n' => Err(Error::NewLine));
- let end = bytes.as_ref().as_ptr() as usize;
- result = Ok(Status::Complete(end - start));
- break;
- }
- if b == b'\n' {
- let end = bytes.as_ref().as_ptr() as usize;
- result = Ok(Status::Complete(end - start));
- break;
- }
- if !is_header_name_token(b) {
- if config.allow_space_before_first_header_name
- && autoshrink.num_headers == 0
- && (b == b' ' || b == b'\t')
- {
- //advance past white space and then try parsing header again
- while let Some(peek) = bytes.peek() {
- if peek == b' ' || peek == b'\t' {
- next!(bytes);
- } else {
- break;
- }
- }
- bytes.slice();
- continue 'headers;
- } else {
- handle_invalid_char!(bytes, b, HeaderName);
- }
- }
-
- #[allow(clippy::never_loop)]
- // parse header name until colon
- let header_name: &str = 'name: loop {
- simd::match_header_name_vectored(bytes);
- let mut b = next!(bytes);
-
- // SAFETY: previously bumped by 1 with next! -> always safe.
- let bslice = unsafe { bytes.slice_skip(1) };
- // SAFETY: previous call to match_header_name_vectored ensured all bytes are valid
- // header name chars, and as such also valid utf-8.
- let name = unsafe { str::from_utf8_unchecked(bslice) };
-
- if b == b':' {
- break 'name name;
- }
-
- if config.allow_spaces_after_header_name {
- while b == b' ' || b == b'\t' {
- b = next!(bytes);
-
- if b == b':' {
- bytes.slice();
- break 'name name;
- }
- }
- }
-
- handle_invalid_char!(bytes, b, HeaderName);
- };
-
- let mut b;
-
- #[allow(clippy::never_loop)]
- let value_slice = 'value: loop {
- // eat white space between colon and value
- 'whitespace_after_colon: loop {
- b = next!(bytes);
- if b == b' ' || b == b'\t' {
- bytes.slice();
- continue 'whitespace_after_colon;
- }
- if is_header_value_token(b) {
- break 'whitespace_after_colon;
- }
-
- if b == b'\r' {
- expect!(bytes.next() == b'\n' => Err(Error::HeaderValue));
- } else if b != b'\n' {
- handle_invalid_char!(bytes, b, HeaderValue);
- }
-
- maybe_continue_after_obsolete_line_folding!(bytes, 'whitespace_after_colon);
-
- let whitespace_slice = bytes.slice();
-
- // This produces an empty slice that points to the beginning
- // of the whitespace.
- break 'value &whitespace_slice[0..0];
- }
-
- 'value_lines: loop {
- // parse value till EOL
-
- simd::match_header_value_vectored(bytes);
- let b = next!(bytes);
-
- //found_ctl
- let skip = if b == b'\r' {
- expect!(bytes.next() == b'\n' => Err(Error::HeaderValue));
- 2
- } else if b == b'\n' {
- 1
- } else {
- handle_invalid_char!(bytes, b, HeaderValue);
- };
-
- maybe_continue_after_obsolete_line_folding!(bytes, 'value_lines);
-
- // SAFETY: having just checked that a newline exists, it's safe to skip it.
- unsafe {
- break 'value bytes.slice_skip(skip);
- }
- }
- };
-
- let uninit_header = match iter.next() {
- Some(header) => header,
- None => break 'headers
- };
-
- // trim trailing whitespace in the header
- let header_value = if let Some(last_visible) = value_slice
- .iter()
- .rposition(|b| *b != b' ' && *b != b'\t' && *b != b'\r' && *b != b'\n')
- {
- // There is at least one non-whitespace character.
- &value_slice[0..last_visible+1]
- } else {
- // There is no non-whitespace character. This can only happen when value_slice is
- // empty.
- value_slice
- };
-
- *uninit_header = MaybeUninit::new(Header {
- name: header_name,
- value: header_value,
- });
- autoshrink.num_headers += 1;
- }
-
- result
-}
-
-/// Parse a buffer of bytes as a chunk size.
-///
-/// The return value, if complete and successful, includes the index of the
-/// buffer that parsing stopped at, and the size of the following chunk.
-///
-/// # Example
-///
-/// ```
-/// let buf = b"4\r\nRust\r\n0\r\n\r\n";
-/// assert_eq!(httparse::parse_chunk_size(buf),
-/// Ok(httparse::Status::Complete((3, 4))));
-/// ```
-pub fn parse_chunk_size(buf: &[u8])
- -> result::Result<Status<(usize, u64)>, InvalidChunkSize> {
- const RADIX: u64 = 16;
- let mut bytes = Bytes::new(buf);
- let mut size = 0;
- let mut in_chunk_size = true;
- let mut in_ext = false;
- let mut count = 0;
- loop {
- let b = next!(bytes);
- match b {
- b'0' ..= b'9' if in_chunk_size => {
- if count > 15 {
- return Err(InvalidChunkSize);
- }
- count += 1;
- if cfg!(debug_assertions) && size > (u64::MAX / RADIX) {
- // actually unreachable!(), because count stops the loop at 15 digits before
- // we can reach u64::MAX / RADIX == 0xfffffffffffffff, which requires 15 hex
- // digits. This stops mirai reporting a false alarm regarding the `size *=
- // RADIX` multiplication below.
- return Err(InvalidChunkSize);
- }
- size *= RADIX;
- size += (b - b'0') as u64;
- },
- b'a' ..= b'f' if in_chunk_size => {
- if count > 15 {
- return Err(InvalidChunkSize);
- }
- count += 1;
- if cfg!(debug_assertions) && size > (u64::MAX / RADIX) {
- return Err(InvalidChunkSize);
- }
- size *= RADIX;
- size += (b + 10 - b'a') as u64;
- }
- b'A' ..= b'F' if in_chunk_size => {
- if count > 15 {
- return Err(InvalidChunkSize);
- }
- count += 1;
- if cfg!(debug_assertions) && size > (u64::MAX / RADIX) {
- return Err(InvalidChunkSize);
- }
- size *= RADIX;
- size += (b + 10 - b'A') as u64;
- }
- b'\r' => {
- match next!(bytes) {
- b'\n' => break,
- _ => return Err(InvalidChunkSize),
- }
- }
- // If we weren't in the extension yet, the ";" signals its start
- b';' if !in_ext => {
- in_ext = true;
- in_chunk_size = false;
- }
- // "Linear white space" is ignored between the chunk size and the
- // extension separator token (";") due to the "implied *LWS rule".
- b'\t' | b' ' if !in_ext && !in_chunk_size => {}
- // LWS can follow the chunk size, but no more digits can come
- b'\t' | b' ' if in_chunk_size => in_chunk_size = false,
- // We allow any arbitrary octet once we are in the extension, since
- // they all get ignored anyway. According to the HTTP spec, valid
- // extensions would have a more strict syntax:
- // (token ["=" (token | quoted-string)])
- // but we gain nothing by rejecting an otherwise valid chunk size.
- _ if in_ext => {}
- // Finally, if we aren't in the extension and we're reading any
- // other octet, the chunk size line is invalid!
- _ => return Err(InvalidChunkSize),
- }
- }
- Ok(Status::Complete((bytes.pos(), size)))
-}
-
-#[cfg(test)]
-mod tests {
- use super::{Error, Request, Response, Status, EMPTY_HEADER, parse_chunk_size};
-
- const NUM_OF_HEADERS: usize = 4;
-
- macro_rules! req {
- ($name:ident, $buf:expr, |$arg:ident| $body:expr) => (
- req! {$name, $buf, Ok(Status::Complete($buf.len())), |$arg| $body }
- );
- ($name:ident, $buf:expr, $len:expr, |$arg:ident| $body:expr) => (
- #[test]
- fn $name() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut req = Request::new(&mut headers[..]);
- let status = req.parse($buf.as_ref());
- assert_eq!(status, $len);
- closure(req);
-
- fn closure($arg: Request) {
- $body
- }
- }
- )
- }
-
- req! {
- test_request_simple,
- b"GET / HTTP/1.1\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 0);
- }
- }
-
- req! {
- test_request_simple_with_query_params,
- b"GET /thing?data=a HTTP/1.1\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/thing?data=a");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 0);
- }
- }
-
- req! {
- test_request_simple_with_whatwg_query_params,
- b"GET /thing?data=a^ HTTP/1.1\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/thing?data=a^");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 0);
- }
- }
-
- req! {
- test_request_headers,
- b"GET / HTTP/1.1\r\nHost: foo.com\r\nCookie: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 2);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo.com");
- assert_eq!(req.headers[1].name, "Cookie");
- assert_eq!(req.headers[1].value, b"");
- }
- }
-
- req! {
- test_request_headers_optional_whitespace,
- b"GET / HTTP/1.1\r\nHost: \tfoo.com\t \r\nCookie: \t \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 2);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo.com");
- assert_eq!(req.headers[1].name, "Cookie");
- assert_eq!(req.headers[1].value, b"");
- }
- }
-
- req! {
- // test the scalar parsing
- test_request_header_value_htab_short,
- b"GET / HTTP/1.1\r\nUser-Agent: some\tagent\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "User-Agent");
- assert_eq!(req.headers[0].value, b"some\tagent");
- }
- }
-
- req! {
- // test the sse42 parsing
- test_request_header_value_htab_med,
- b"GET / HTTP/1.1\r\nUser-Agent: 1234567890some\tagent\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "User-Agent");
- assert_eq!(req.headers[0].value, b"1234567890some\tagent");
- }
- }
-
- req! {
- // test the avx2 parsing
- test_request_header_value_htab_long,
- b"GET / HTTP/1.1\r\nUser-Agent: 1234567890some\t1234567890agent1234567890\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "User-Agent");
- assert_eq!(req.headers[0].value, &b"1234567890some\t1234567890agent1234567890"[..]);
- }
- }
-
- req! {
- // test the avx2 parsing
- test_request_header_no_space_after_colon,
- b"GET / HTTP/1.1\r\nUser-Agent:omg-no-space1234567890some1234567890agent1234567890\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "User-Agent");
- assert_eq!(req.headers[0].value, &b"omg-no-space1234567890some1234567890agent1234567890"[..]);
- }
- }
-
- req! {
- test_request_headers_max,
- b"GET / HTTP/1.1\r\nA: A\r\nB: B\r\nC: C\r\nD: D\r\n\r\n",
- |req| {
- assert_eq!(req.headers.len(), NUM_OF_HEADERS);
- }
- }
-
- req! {
- test_request_multibyte,
- b"GET / HTTP/1.1\r\nHost: foo.com\r\nUser-Agent: \xe3\x81\xb2\xe3/1.0\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 2);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo.com");
- assert_eq!(req.headers[1].name, "User-Agent");
- assert_eq!(req.headers[1].value, b"\xe3\x81\xb2\xe3/1.0");
- }
- }
-
- // A single byte which is part of a method is not invalid
- req! {
- test_request_one_byte_method,
- b"G", Ok(Status::Partial),
- |_req| {}
- }
-
- // A subset of a method is a partial method, not invalid
- req! {
- test_request_partial_method,
- b"GE", Ok(Status::Partial),
- |_req| {}
- }
-
- // A method, without the delimiting space, is a partial request
- req! {
- test_request_method_no_delimiter,
- b"GET", Ok(Status::Partial),
- |_req| {}
- }
-
- // Regression test: assert that a partial read with just the method and
- // space results in a partial, rather than a token error from uri parsing.
- req! {
- test_request_method_only,
- b"GET ", Ok(Status::Partial),
- |_req| {}
- }
-
- req! {
- test_request_partial,
- b"GET / HTTP/1.1\r\n\r", Ok(Status::Partial),
- |_req| {}
- }
-
- req! {
- test_request_partial_version,
- b"GET / HTTP/1.", Ok(Status::Partial),
- |_req| {}
- }
-
- req! {
- test_request_method_path_no_delimiter,
- b"GET /", Ok(Status::Partial),
- |_req| {}
- }
-
- req! {
- test_request_method_path_only,
- b"GET / ", Ok(Status::Partial),
- |_req| {}
- }
-
- req! {
- test_request_partial_parses_headers_as_much_as_it_can,
- b"GET / HTTP/1.1\r\nHost: yolo\r\n",
- Ok(crate::Status::Partial),
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), NUM_OF_HEADERS); // doesn't slice since not Complete
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"yolo");
- }
- }
-
- req! {
- test_request_newlines,
- b"GET / HTTP/1.1\nHost: foo.bar\n\n",
- |_r| {}
- }
-
- req! {
- test_request_empty_lines_prefix,
- b"\r\n\r\nGET / HTTP/1.1\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 0);
- }
- }
-
- req! {
- test_request_empty_lines_prefix_lf_only,
- b"\n\nGET / HTTP/1.1\n\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 0);
- }
- }
-
- req! {
- test_request_path_backslash,
- b"\n\nGET /\\?wayne\\=5 HTTP/1.1\n\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/\\?wayne\\=5");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 0);
- }
- }
-
- req! {
- test_request_with_invalid_token_delimiter,
- b"GET\n/ HTTP/1.1\r\nHost: foo.bar\r\n\r\n",
- Err(crate::Error::Token),
- |_r| {}
- }
-
-
- req! {
- test_request_with_invalid_but_short_version,
- b"GET / HTTP/1!",
- Err(crate::Error::Version),
- |_r| {}
- }
-
- req! {
- test_request_with_empty_method,
- b" / HTTP/1.1\r\n\r\n",
- Err(crate::Error::Token),
- |_r| {}
- }
-
- req! {
- test_request_with_empty_path,
- b"GET HTTP/1.1\r\n\r\n",
- Err(crate::Error::Token),
- |_r| {}
- }
-
- req! {
- test_request_with_empty_method_and_path,
- b" HTTP/1.1\r\n\r\n",
- Err(crate::Error::Token),
- |_r| {}
- }
-
- macro_rules! res {
- ($name:ident, $buf:expr, |$arg:ident| $body:expr) => (
- res! {$name, $buf, Ok(Status::Complete($buf.len())), |$arg| $body }
- );
- ($name:ident, $buf:expr, $len:expr, |$arg:ident| $body:expr) => (
- #[test]
- fn $name() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut res = Response::new(&mut headers[..]);
- let status = res.parse($buf.as_ref());
- assert_eq!(status, $len);
- closure(res);
-
- fn closure($arg: Response) {
- $body
- }
- }
- )
- }
-
- res! {
- test_response_simple,
- b"HTTP/1.1 200 OK\r\n\r\n",
- |res| {
- assert_eq!(res.version.unwrap(), 1);
- assert_eq!(res.code.unwrap(), 200);
- assert_eq!(res.reason.unwrap(), "OK");
- }
- }
-
- res! {
- test_response_newlines,
- b"HTTP/1.0 403 Forbidden\nServer: foo.bar\n\n",
- |_r| {}
- }
-
- res! {
- test_response_reason_missing,
- b"HTTP/1.1 200 \r\n\r\n",
- |res| {
- assert_eq!(res.version.unwrap(), 1);
- assert_eq!(res.code.unwrap(), 200);
- assert_eq!(res.reason.unwrap(), "");
- }
- }
-
- res! {
- test_response_reason_missing_no_space,
- b"HTTP/1.1 200\r\n\r\n",
- |res| {
- assert_eq!(res.version.unwrap(), 1);
- assert_eq!(res.code.unwrap(), 200);
- assert_eq!(res.reason.unwrap(), "");
- }
- }
-
- res! {
- test_response_reason_missing_no_space_with_headers,
- b"HTTP/1.1 200\r\nFoo: bar\r\n\r\n",
- |res| {
- assert_eq!(res.version.unwrap(), 1);
- assert_eq!(res.code.unwrap(), 200);
- assert_eq!(res.reason.unwrap(), "");
- assert_eq!(res.headers.len(), 1);
- assert_eq!(res.headers[0].name, "Foo");
- assert_eq!(res.headers[0].value, b"bar");
- }
- }
-
- res! {
- test_response_reason_with_space_and_tab,
- b"HTTP/1.1 101 Switching Protocols\t\r\n\r\n",
- |res| {
- assert_eq!(res.version.unwrap(), 1);
- assert_eq!(res.code.unwrap(), 101);
- assert_eq!(res.reason.unwrap(), "Switching Protocols\t");
- }
- }
-
- static RESPONSE_REASON_WITH_OBS_TEXT_BYTE: &[u8] = b"HTTP/1.1 200 X\xFFZ\r\n\r\n";
- res! {
- test_response_reason_with_obsolete_text_byte,
- RESPONSE_REASON_WITH_OBS_TEXT_BYTE,
- |res| {
- assert_eq!(res.version.unwrap(), 1);
- assert_eq!(res.code.unwrap(), 200);
- // Empty string fallback in case of obs-text
- assert_eq!(res.reason.unwrap(), "");
- }
- }
-
- res! {
- test_response_reason_with_nul_byte,
- b"HTTP/1.1 200 \x00\r\n\r\n",
- Err(crate::Error::Status),
- |_res| {}
- }
-
- res! {
- test_response_version_missing_space,
- b"HTTP/1.1",
- Ok(Status::Partial),
- |_res| {}
- }
-
- res! {
- test_response_code_missing_space,
- b"HTTP/1.1 200",
- Ok(Status::Partial),
- |_res| {}
- }
-
- res! {
- test_response_partial_parses_headers_as_much_as_it_can,
- b"HTTP/1.1 200 OK\r\nServer: yolo\r\n",
- Ok(crate::Status::Partial),
- |res| {
- assert_eq!(res.version.unwrap(), 1);
- assert_eq!(res.code.unwrap(), 200);
- assert_eq!(res.reason.unwrap(), "OK");
- assert_eq!(res.headers.len(), NUM_OF_HEADERS); // doesn't slice since not Complete
- assert_eq!(res.headers[0].name, "Server");
- assert_eq!(res.headers[0].value, b"yolo");
- }
- }
-
- res! {
- test_response_empty_lines_prefix_lf_only,
- b"\n\nHTTP/1.1 200 OK\n\n",
- |_res| {}
- }
-
- res! {
- test_response_no_cr,
- b"HTTP/1.0 200\nContent-type: text/html\n\n",
- |res| {
- assert_eq!(res.version.unwrap(), 0);
- assert_eq!(res.code.unwrap(), 200);
- assert_eq!(res.reason.unwrap(), "");
- assert_eq!(res.headers.len(), 1);
- assert_eq!(res.headers[0].name, "Content-type");
- assert_eq!(res.headers[0].value, b"text/html");
- }
- }
-
- /// Check all subset permutations of a partial request line with no headers
- #[test]
- fn partial_permutations() {
- let req_str = "GET / HTTP/1.1\r\n\r\n";
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut req = Request::new(&mut headers[..]);
- for i in 0..req_str.len() {
- let status = req.parse(req_str[..i].as_bytes());
- assert_eq!(
- status,
- Ok(Status::Partial),
- "partial request line should return partial. \
- Portion which failed: '{seg}' (below {i})",
- seg = &req_str[..i]
- );
- }
- }
-
- static RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON: &[u8] =
- b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials : true\r\nBread: baguette\r\n\r\n";
-
- #[test]
- fn test_forbid_response_with_whitespace_between_header_name_and_colon() {
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
- let result = response.parse(RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
-
- assert_eq!(result, Err(crate::Error::HeaderName));
- }
-
- #[test]
- fn test_allow_response_with_whitespace_between_header_name_and_colon() {
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_spaces_after_header_name_in_responses(true)
- .parse_response(&mut response, RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
-
- assert_eq!(result, Ok(Status::Complete(77)));
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 2);
- assert_eq!(response.headers[0].name, "Access-Control-Allow-Credentials");
- assert_eq!(response.headers[0].value, &b"true"[..]);
- assert_eq!(response.headers[1].name, "Bread");
- assert_eq!(response.headers[1].value, &b"baguette"[..]);
- }
-
- #[test]
- fn test_ignore_header_line_with_whitespaces_after_header_name_in_response() {
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
-
- assert_eq!(result, Ok(Status::Complete(77)));
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "Bread");
- assert_eq!(response.headers[0].value, &b"baguette"[..]);
- }
-
- static REQUEST_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON: &[u8] =
- b"GET / HTTP/1.1\r\nHost : localhost\r\n\r\n";
-
- #[test]
- fn test_forbid_request_with_whitespace_between_header_name_and_colon() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut request = Request::new(&mut headers[..]);
- let result = request.parse(REQUEST_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
-
- assert_eq!(result, Err(crate::Error::HeaderName));
- }
-
- #[test]
- fn test_ignore_header_line_with_whitespaces_after_header_name_in_request() {
- let mut headers = [EMPTY_HEADER; 2];
- let mut request = Request::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_requests(true)
- .parse_request(&mut request, REQUEST_WITH_WHITESPACE_BETWEEN_HEADER_NAME_AND_COLON);
-
- assert_eq!(result, Ok(Status::Complete(36)));
- }
-
- static RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_START: &[u8] =
- b"HTTP/1.1 200 OK\r\nLine-Folded-Header: \r\n \r\n hello there\r\n\r\n";
-
- #[test]
- fn test_forbid_response_with_obsolete_line_folding_at_start() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut response = Response::new(&mut headers[..]);
- let result = response.parse(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_START);
-
- assert_eq!(result, Err(crate::Error::HeaderName));
- }
-
- #[test]
- fn test_allow_response_with_obsolete_line_folding_at_start() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut response = Response::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_obsolete_multiline_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_START);
-
- assert_eq!(result, Ok(Status::Complete(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_START.len())));
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "Line-Folded-Header");
- assert_eq!(response.headers[0].value, &b"hello there"[..]);
- }
-
- static RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_END: &[u8] =
- b"HTTP/1.1 200 OK\r\nLine-Folded-Header: hello there\r\n \r\n \r\n\r\n";
-
- #[test]
- fn test_forbid_response_with_obsolete_line_folding_at_end() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut response = Response::new(&mut headers[..]);
- let result = response.parse(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_END);
-
- assert_eq!(result, Err(crate::Error::HeaderName));
- }
-
- #[test]
- fn test_allow_response_with_obsolete_line_folding_at_end() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut response = Response::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_obsolete_multiline_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_END);
-
- assert_eq!(result, Ok(Status::Complete(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_AT_END.len())));
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "Line-Folded-Header");
- assert_eq!(response.headers[0].value, &b"hello there"[..]);
- }
-
- static RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_MIDDLE: &[u8] =
- b"HTTP/1.1 200 OK\r\nLine-Folded-Header: hello \r\n \r\n there\r\n\r\n";
-
- #[test]
- fn test_forbid_response_with_obsolete_line_folding_in_middle() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut response = Response::new(&mut headers[..]);
- let result = response.parse(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_MIDDLE);
-
- assert_eq!(result, Err(crate::Error::HeaderName));
- }
-
- #[test]
- fn test_allow_response_with_obsolete_line_folding_in_middle() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut response = Response::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_obsolete_multiline_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_MIDDLE);
-
- assert_eq!(result, Ok(Status::Complete(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_MIDDLE.len())));
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "Line-Folded-Header");
- assert_eq!(response.headers[0].value, &b"hello \r\n \r\n there"[..]);
- }
-
- static RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_EMPTY_HEADER: &[u8] =
- b"HTTP/1.1 200 OK\r\nLine-Folded-Header: \r\n \r\n \r\n\r\n";
-
- #[test]
- fn test_forbid_response_with_obsolete_line_folding_in_empty_header() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut response = Response::new(&mut headers[..]);
- let result = response.parse(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_EMPTY_HEADER);
-
- assert_eq!(result, Err(crate::Error::HeaderName));
- }
-
- #[test]
- fn test_allow_response_with_obsolete_line_folding_in_empty_header() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut response = Response::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_obsolete_multiline_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_EMPTY_HEADER);
-
- assert_eq!(result, Ok(Status::Complete(RESPONSE_WITH_OBSOLETE_LINE_FOLDING_IN_EMPTY_HEADER.len())));
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "Line-Folded-Header");
- assert_eq!(response.headers[0].value, &b""[..]);
- }
-
- #[test]
- fn test_chunk_size() {
- assert_eq!(parse_chunk_size(b"0\r\n"), Ok(Status::Complete((3, 0))));
- assert_eq!(parse_chunk_size(b"12\r\nchunk"), Ok(Status::Complete((4, 18))));
- assert_eq!(parse_chunk_size(b"3086d\r\n"), Ok(Status::Complete((7, 198765))));
- assert_eq!(parse_chunk_size(b"3735AB1;foo bar*\r\n"), Ok(Status::Complete((18, 57891505))));
- assert_eq!(parse_chunk_size(b"3735ab1 ; baz \r\n"), Ok(Status::Complete((16, 57891505))));
- assert_eq!(parse_chunk_size(b"77a65\r"), Ok(Status::Partial));
- assert_eq!(parse_chunk_size(b"ab"), Ok(Status::Partial));
- assert_eq!(parse_chunk_size(b"567f8a\rfoo"), Err(crate::InvalidChunkSize));
- assert_eq!(parse_chunk_size(b"567f8a\rfoo"), Err(crate::InvalidChunkSize));
- assert_eq!(parse_chunk_size(b"567xf8a\r\n"), Err(crate::InvalidChunkSize));
- assert_eq!(parse_chunk_size(b"ffffffffffffffff\r\n"), Ok(Status::Complete((18, u64::MAX))));
- assert_eq!(parse_chunk_size(b"1ffffffffffffffff\r\n"), Err(crate::InvalidChunkSize));
- assert_eq!(parse_chunk_size(b"Affffffffffffffff\r\n"), Err(crate::InvalidChunkSize));
- assert_eq!(parse_chunk_size(b"fffffffffffffffff\r\n"), Err(crate::InvalidChunkSize));
- }
-
- static RESPONSE_WITH_MULTIPLE_SPACE_DELIMITERS: &[u8] =
- b"HTTP/1.1 200 OK\r\n\r\n";
-
- #[test]
- fn test_forbid_response_with_multiple_space_delimiters() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut response = Response::new(&mut headers[..]);
- let result = response.parse(RESPONSE_WITH_MULTIPLE_SPACE_DELIMITERS);
-
- assert_eq!(result, Err(crate::Error::Status));
- }
-
- #[test]
- fn test_allow_response_with_multiple_space_delimiters() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut response = Response::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_response_status_delimiters(true)
- .parse_response(&mut response, RESPONSE_WITH_MULTIPLE_SPACE_DELIMITERS);
-
- assert_eq!(result, Ok(Status::Complete(RESPONSE_WITH_MULTIPLE_SPACE_DELIMITERS.len())));
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 0);
- }
-
- /// This is technically allowed by the spec, but we only support multiple spaces as an option,
- /// not stray `\r`s.
- static RESPONSE_WITH_WEIRD_WHITESPACE_DELIMITERS: &[u8] =
- b"HTTP/1.1 200\rOK\r\n\r\n";
-
- #[test]
- fn test_forbid_response_with_weird_whitespace_delimiters() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut response = Response::new(&mut headers[..]);
- let result = response.parse(RESPONSE_WITH_WEIRD_WHITESPACE_DELIMITERS);
-
- assert_eq!(result, Err(crate::Error::Status));
- }
-
- #[test]
- fn test_still_forbid_response_with_weird_whitespace_delimiters() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut response = Response::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_response_status_delimiters(true)
- .parse_response(&mut response, RESPONSE_WITH_WEIRD_WHITESPACE_DELIMITERS);
- assert_eq!(result, Err(crate::Error::Status));
- }
-
- static REQUEST_WITH_MULTIPLE_SPACE_DELIMITERS: &[u8] =
- b"GET / HTTP/1.1\r\n\r\n";
-
- #[test]
- fn test_forbid_request_with_multiple_space_delimiters() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut request = Request::new(&mut headers[..]);
- let result = request.parse(REQUEST_WITH_MULTIPLE_SPACE_DELIMITERS);
-
- assert_eq!(result, Err(crate::Error::Token));
- }
-
- #[test]
- fn test_allow_request_with_multiple_space_delimiters() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut request = Request::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_request_line_delimiters(true)
- .parse_request(&mut request, REQUEST_WITH_MULTIPLE_SPACE_DELIMITERS);
-
- assert_eq!(result, Ok(Status::Complete(REQUEST_WITH_MULTIPLE_SPACE_DELIMITERS.len())));
- assert_eq!(request.method.unwrap(), "GET");
- assert_eq!(request.path.unwrap(), "/");
- assert_eq!(request.version.unwrap(), 1);
- assert_eq!(request.headers.len(), 0);
- }
-
- /// This is technically allowed by the spec, but we only support multiple spaces as an option,
- /// not stray `\r`s.
- static REQUEST_WITH_WEIRD_WHITESPACE_DELIMITERS: &[u8] =
- b"GET\r/\rHTTP/1.1\r\n\r\n";
-
- #[test]
- fn test_forbid_request_with_weird_whitespace_delimiters() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut request = Request::new(&mut headers[..]);
- let result = request.parse(REQUEST_WITH_WEIRD_WHITESPACE_DELIMITERS);
-
- assert_eq!(result, Err(crate::Error::Token));
- }
-
- #[test]
- fn test_still_forbid_request_with_weird_whitespace_delimiters() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut request = Request::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_request_line_delimiters(true)
- .parse_request(&mut request, REQUEST_WITH_WEIRD_WHITESPACE_DELIMITERS);
- assert_eq!(result, Err(crate::Error::Token));
- }
-
- static REQUEST_WITH_MULTIPLE_SPACES_AND_BAD_PATH: &[u8] = b"GET /foo ohno HTTP/1.1\r\n\r\n";
-
- #[test]
- fn test_request_with_multiple_spaces_and_bad_path() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut request = Request::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_request_line_delimiters(true)
- .parse_request(&mut request, REQUEST_WITH_MULTIPLE_SPACES_AND_BAD_PATH);
- assert_eq!(result, Err(crate::Error::Version));
- }
-
- // This test ensure there is an error when there is a DEL character in the path
- // since we allow all char from 0x21 code except DEL, this test ensure that DEL
- // is not allowed in the path
- static REQUEST_WITH_DEL_IN_PATH: &[u8] = b"GET /foo\x7Fohno HTTP/1.1\r\n\r\n";
-
- #[test]
- fn test_request_with_del_in_path() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut request = Request::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_request_line_delimiters(true)
- .parse_request(&mut request, crate::tests::REQUEST_WITH_DEL_IN_PATH);
- assert_eq!(result, Err(crate::Error::Token));
- }
-
- #[test]
- #[cfg_attr(miri, ignore)] // Miri is too slow for this test
- fn test_all_utf8_char_in_paths() {
- // two code points
- for i in 128..256 {
- for j in 128..256 {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut request = Request::new(&mut headers[..]);
- let bytes = [i as u8, j as u8];
-
- match core::str::from_utf8(&bytes) {
- Ok(s) => {
- let first_line = format!("GET /{} HTTP/1.1\r\n\r\n", s);
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_request_line_delimiters(true)
- .parse_request(&mut request, first_line.as_bytes());
-
- assert_eq!(result, Ok(Status::Complete(20)), "failed for utf8 char i: {}, j: {}", i, j);
- },
- Err(_) => {
- let mut first_line = b"GET /".to_vec();
- first_line.extend(&bytes);
- first_line.extend(b" HTTP/1.1\r\n\r\n");
-
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_request_line_delimiters(true)
- .parse_request(&mut request, first_line.as_slice());
-
- assert_eq!(result, Err(crate::Error::Token), "failed for utf8 char i: {}, j: {}", i, j);
- },
- };
-
- // three code points starting from 0xe0
- if i < 0xe0 {
- continue;
- }
-
- for k in 128..256 {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut request = Request::new(&mut headers[..]);
- let bytes = [i as u8, j as u8, k as u8];
-
- match core::str::from_utf8(&bytes) {
- Ok(s) => {
- let first_line = format!("GET /{} HTTP/1.1\r\n\r\n", s);
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_request_line_delimiters(true)
- .parse_request(&mut request, first_line.as_bytes());
-
- assert_eq!(result, Ok(Status::Complete(21)), "failed for utf8 char i: {}, j: {}, k: {}", i, j, k);
- },
- Err(_) => {
- let mut first_line = b"GET /".to_vec();
- first_line.extend(&bytes);
- first_line.extend(b" HTTP/1.1\r\n\r\n");
-
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_request_line_delimiters(true)
- .parse_request(&mut request, first_line.as_slice());
-
- assert_eq!(result, Err(crate::Error::Token), "failed for utf8 char i: {}, j: {}, k: {}", i, j, k);
- },
- };
-
- // four code points starting from 0xf0
- if i < 0xf0 {
- continue;
- }
-
- for l in 128..256 {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut request = Request::new(&mut headers[..]);
- let bytes = [i as u8, j as u8, k as u8, l as u8];
-
- match core::str::from_utf8(&bytes) {
- Ok(s) => {
- let first_line = format!("GET /{} HTTP/1.1\r\n\r\n", s);
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_request_line_delimiters(true)
- .parse_request(&mut request, first_line.as_bytes());
-
- assert_eq!(result, Ok(Status::Complete(22)), "failed for utf8 char i: {}, j: {}, k: {}, l: {}", i, j, k, l);
- },
- Err(_) => {
- let mut first_line = b"GET /".to_vec();
- first_line.extend(&bytes);
- first_line.extend(b" HTTP/1.1\r\n\r\n");
-
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_request_line_delimiters(true)
- .parse_request(&mut request, first_line.as_slice());
-
- assert_eq!(result, Err(crate::Error::Token), "failed for utf8 char i: {}, j: {}, k: {}, l: {}", i, j, k, l);
- },
- };
- }
- }
- }
- }
- }
-
- static RESPONSE_WITH_SPACES_IN_CODE: &[u8] = b"HTTP/1.1 99 200 OK\r\n\r\n";
-
- #[test]
- fn test_response_with_spaces_in_code() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut response = Response::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_multiple_spaces_in_response_status_delimiters(true)
- .parse_response(&mut response, RESPONSE_WITH_SPACES_IN_CODE);
- assert_eq!(result, Err(crate::Error::Status));
- }
-
- #[test]
- fn test_response_with_empty_header_name() {
- const RESPONSE: &[u8] =
- b"HTTP/1.1 200 OK\r\n: hello\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .allow_spaces_after_header_name_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Ok(Status::Complete(45)));
-
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "Bread");
- assert_eq!(response.headers[0].value, &b"baguette"[..]);
- }
-
- #[test]
- fn test_request_with_empty_header_name() {
- const RESPONSE: &[u8] =
- b"GET / HTTP/1.1\r\n: hello\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_request(&mut request, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_requests(true)
- .parse_request(&mut request, RESPONSE);
- assert_eq!(result, Ok(Status::Complete(44)));
- }
-
- #[test]
- fn test_request_with_whitespace_between_header_name_and_colon() {
- const REQUEST: &[u8] =
- b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials : true\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .allow_spaces_after_header_name_in_responses(true)
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
-
- .ignore_invalid_headers_in_responses(true)
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderName));
- }
-
- #[test]
- fn test_response_with_invalid_char_between_header_name_and_colon() {
- const RESPONSE: &[u8] =
- b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials\xFF : true\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .allow_spaces_after_header_name_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE);
-
- assert_eq!(result, Ok(Status::Complete(79)));
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "Bread");
- assert_eq!(response.headers[0].value, &b"baguette"[..]);
- }
-
- #[test]
- fn test_request_with_invalid_char_between_header_name_and_colon() {
- const REQUEST: &[u8] =
- b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials\xFF : true\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_requests(true)
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Ok(Status::Complete(78)));
- }
-
- #[test]
- fn test_ignore_header_line_with_missing_colon_in_response() {
- const RESPONSE: &[u8] =
- b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Ok(Status::Complete(70)));
-
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "Bread");
- assert_eq!(response.headers[0].value, &b"baguette"[..]);
- }
-
- #[test]
- fn test_ignore_header_line_with_missing_colon_in_request() {
- const REQUEST: &[u8] =
- b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_requests(true)
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Ok(Status::Complete(69)));
- }
-
- #[test]
- fn test_response_header_with_missing_colon_with_folding() {
- const RESPONSE: &[u8] =
- b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials \r\n hello\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .allow_obsolete_multiline_headers_in_responses(true)
- .allow_spaces_after_header_name_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Ok(Status::Complete(81)));
-
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "Bread");
- assert_eq!(response.headers[0].value, &b"baguette"[..]);
- }
-
- #[test]
- fn test_request_header_with_missing_colon_with_folding() {
- const REQUEST: &[u8] =
- b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials \r\n hello\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_requests(true)
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Ok(Status::Complete(80)));
- }
-
- #[test]
- fn test_response_header_with_nul_in_header_name() {
- const RESPONSE: &[u8] =
- b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Cred\0entials: hello\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderName));
- }
-
- #[test]
- fn test_request_header_with_nul_in_header_name() {
- const REQUEST: &[u8] =
- b"GET / HTTP/1.1\r\nAccess-Control-Allow-Cred\0entials: hello\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_requests(true)
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderName));
- }
-
- #[test]
- fn test_header_with_cr_in_header_name() {
- const RESPONSE: &[u8] =
- b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Cred\rentials: hello\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- const REQUEST: &[u8] =
- b"GET / HTTP/1.1\r\nAccess-Control-Allow-Cred\rentials: hello\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_requests(true)
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderName));
- }
-
- #[test]
- fn test_header_with_nul_in_whitespace_before_colon() {
- const RESPONSE: &[u8] =
- b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials \0: hello\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .allow_spaces_after_header_name_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- let result = crate::ParserConfig::default()
- .allow_spaces_after_header_name_in_responses(true)
- .ignore_invalid_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderName));
-
- const REQUEST: &[u8] =
- b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials \0: hello\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_requests(true)
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderName));
- }
-
- #[test]
- fn test_header_with_nul_in_value() {
- const RESPONSE: &[u8] =
- b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials: hell\0o\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderValue));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderValue));
-
- const REQUEST: &[u8] =
- b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials: hell\0o\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderValue));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_requests(true)
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderValue));
- }
-
- #[test]
- fn test_header_with_invalid_char_in_value() {
- const RESPONSE: &[u8] =
- b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials: hell\x01o\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderValue));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Ok(Status::Complete(78)));
-
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "Bread");
- assert_eq!(response.headers[0].value, &b"baguette"[..]);
-
- const REQUEST: &[u8] =
- b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials: hell\x01o\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderValue));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_requests(true)
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Ok(Status::Complete(77)));
-
- assert_eq!(request.version.unwrap(), 1);
- assert_eq!(request.method.unwrap(), "GET");
- assert_eq!(request.path.unwrap(), "/");
- assert_eq!(request.headers.len(), 1);
- assert_eq!(request.headers[0].name, "Bread");
- assert_eq!(request.headers[0].value, &b"baguette"[..]);
- }
-
- #[test]
- fn test_header_with_invalid_char_in_value_with_folding() {
- const RESPONSE: &[u8] =
- b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Credentials: hell\x01o \n world!\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut response = Response::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Err(crate::Error::HeaderValue));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_responses(true)
- .parse_response(&mut response, RESPONSE);
- assert_eq!(result, Ok(Status::Complete(88)));
-
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "Bread");
- assert_eq!(response.headers[0].value, &b"baguette"[..]);
-
- const REQUEST: &[u8] =
- b"GET / HTTP/1.1\r\nAccess-Control-Allow-Credentials: hell\x01o \n world!\r\nBread: baguette\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 2];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default()
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Err(crate::Error::HeaderValue));
-
- let result = crate::ParserConfig::default()
- .ignore_invalid_headers_in_requests(true)
- .parse_request(&mut request, REQUEST);
- assert_eq!(result, Ok(Status::Complete(87)));
-
- assert_eq!(request.version.unwrap(), 1);
- assert_eq!(request.method.unwrap(), "GET");
- assert_eq!(request.path.unwrap(), "/");
- assert_eq!(request.headers.len(), 1);
- assert_eq!(request.headers[0].name, "Bread");
- assert_eq!(request.headers[0].value, &b"baguette"[..]);
- }
-
- #[test]
- fn test_method_within_buffer() {
- const REQUEST: &[u8] = b"GET / HTTP/1.1\r\n\r\n";
-
- let mut headers = [EMPTY_HEADER; 0];
- let mut request = Request::new(&mut headers[..]);
-
- crate::ParserConfig::default()
- .parse_request(&mut request, REQUEST)
- .unwrap();
-
- // SAFETY: will not wrap
- let buf_end = unsafe { REQUEST.as_ptr().add(REQUEST.len()) };
- // Check that the method str is within the buffer
- let method = request.method.unwrap();
- assert!(REQUEST.as_ptr() <= method.as_ptr());
- assert!(method.as_ptr() <= buf_end);
- }
-
- static RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER: &[u8] =
- b"HTTP/1.1 200 OK\r\n Space-Before-Header: hello there\r\n\r\n";
-
- #[test]
- fn test_forbid_response_with_space_before_first_header() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut response = Response::new(&mut headers[..]);
- let result = response.parse(RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER);
-
- assert_eq!(result, Err(crate::Error::HeaderName));
- }
-
- #[test]
- fn test_allow_response_response_with_space_before_first_header() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut response = Response::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .allow_space_before_first_header_name(true)
- .parse_response(&mut response, RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER);
-
- assert_eq!(
- result,
- Ok(Status::Complete(
- RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER.len()
- ))
- );
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "Space-Before-Header");
- assert_eq!(response.headers[0].value, &b"hello there"[..]);
- }
-
- #[test]
- fn test_no_space_after_colon() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut response = Response::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .parse_response(&mut response, b"HTTP/1.1 200 OK\r\nfoo:bar\r\n\r\n");
-
- assert_eq!(result, Ok(Status::Complete(28)));
- assert_eq!(response.version.unwrap(), 1);
- assert_eq!(response.code.unwrap(), 200);
- assert_eq!(response.reason.unwrap(), "OK");
- assert_eq!(response.headers.len(), 1);
- assert_eq!(response.headers[0].name, "foo");
- assert_eq!(response.headers[0].value, &b"bar"[..]);
- }
-
- #[test]
- fn test_request_with_leading_space() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut request = Request::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .parse_request(&mut request, b" GET / HTTP/1.1\r\nfoo:bar\r\n\r\n");
-
- assert_eq!(result, Err(Error::Token));
- }
-
- #[test]
- fn test_request_with_invalid_method() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut request = Request::new(&mut headers[..]);
- let result = crate::ParserConfig::default()
- .parse_request(&mut request, b"P()ST / HTTP/1.1\r\nfoo:bar\r\n\r\n");
-
- assert_eq!(result, Err(Error::Token));
- }
-
- #[test]
- fn test_utf8_in_path_ok() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default().parse_request(&mut request, b"GET /test?post=I\xE2\x80\x99msorryIforkedyou HTTP/1.1\r\nHost: example.org\r\n\r\n");
-
- assert_eq!(result, Ok(Status::Complete(67)));
- assert_eq!(request.version.unwrap(), 1);
- assert_eq!(request.method.unwrap(), "GET");
- assert_eq!(request.path.unwrap(), "/test?post=I’msorryIforkedyou");
- assert_eq!(request.headers.len(), 1);
- assert_eq!(request.headers[0].name, "Host");
- assert_eq!(request.headers[0].value, &b"example.org"[..]);
- }
-
- #[test]
- fn test_bad_utf8_in_path() {
- let mut headers = [EMPTY_HEADER; 1];
- let mut request = Request::new(&mut headers[..]);
-
- let result = crate::ParserConfig::default().parse_request(&mut request, b"GET /test?post=I\xE2msorryIforkedyou HTTP/1.1\r\nHost: example.org\r\n\r\n");
-
- assert_eq!(result, Err(crate::Error::Token));
- }
-}
diff --git a/vendor/httparse/src/macros.rs b/vendor/httparse/src/macros.rs
deleted file mode 100644
index 751f60b3..00000000
--- a/vendor/httparse/src/macros.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-//! Utility macros
-
-macro_rules! next {
- ($bytes:ident) => ({
- match $bytes.next() {
- Some(b) => b,
- None => return Ok(Status::Partial)
- }
- })
-}
-
-macro_rules! expect {
- ($bytes:ident.next() == $pat:pat => $ret:expr) => {
- expect!(next!($bytes) => $pat |? $ret)
- };
- ($e:expr => $pat:pat |? $ret:expr) => {
- match $e {
- v@$pat => v,
- _ => return $ret
- }
- };
-}
-
-macro_rules! complete {
- ($e:expr) => {
- match $e? {
- Status::Complete(v) => v,
- Status::Partial => return Ok(Status::Partial)
- }
- }
-}
-
-macro_rules! byte_map {
- ($($p:pat)|+) => {{
- const fn make_map() -> [bool; 256] {
- let mut ret = [false; 256];
- let mut i = 0;
- while i < 256 {
- ret[i] = matches!(i as u8, $($p)|+);
- i += 1;
- }
- ret
- }
- make_map()
- }}
-}
-
-macro_rules! space {
- ($bytes:ident or $err:expr) => ({
- expect!($bytes.next() == b' ' => Err($err));
- $bytes.slice();
- })
-}
-
-macro_rules! newline {
- ($bytes:ident) => ({
- match next!($bytes) {
- b'\r' => {
- expect!($bytes.next() == b'\n' => Err(Error::NewLine));
- $bytes.slice();
- },
- b'\n' => {
- $bytes.slice();
- },
- _ => return Err(Error::NewLine)
- }
- })
-}
diff --git a/vendor/httparse/src/simd/avx2.rs b/vendor/httparse/src/simd/avx2.rs
deleted file mode 100644
index 2adf0a28..00000000
--- a/vendor/httparse/src/simd/avx2.rs
+++ /dev/null
@@ -1,206 +0,0 @@
-use crate::iter::Bytes;
-
-#[inline]
-#[target_feature(enable = "avx2")]
-pub unsafe fn match_uri_vectored(bytes: &mut Bytes) {
- while bytes.as_ref().len() >= 32 {
-
- let advance = match_url_char_32_avx(bytes.as_ref());
-
- bytes.advance(advance);
-
- if advance != 32 {
- return;
- }
- }
- // NOTE: use SWAR for <32B, more efficient than falling back to SSE4.2
- super::swar::match_uri_vectored(bytes)
-}
-
-#[inline(always)]
-#[allow(non_snake_case, overflowing_literals)]
-#[allow(unused)]
-unsafe fn match_url_char_32_avx(buf: &[u8]) -> usize {
- // NOTE: This check might be not necessary since this function is only used in
- // `match_uri_vectored` where buffer overflow is taken care of.
- debug_assert!(buf.len() >= 32);
-
- #[cfg(target_arch = "x86")]
- use core::arch::x86::*;
- #[cfg(target_arch = "x86_64")]
- use core::arch::x86_64::*;
-
- // pointer to buffer
- let ptr = buf.as_ptr();
-
- // %x21-%x7e %x80-%xff
- //
- // Character ranges allowed by this function, can also be interpreted as:
- // 33 =< (x != 127) =< 255
- //
- // Create a vector full of DEL (0x7f) characters.
- let DEL: __m256i = _mm256_set1_epi8(0x7f);
- // Create a vector full of exclamation mark (!) (0x21) characters.
- // Used as lower threshold, characters in URLs cannot be smaller than this.
- let LOW: __m256i = _mm256_set1_epi8(0x21);
-
- // Load a chunk of 32 bytes from `ptr` as a vector.
- // We can check 32 bytes in parallel at most with AVX2 since
- // YMM registers can only have 256 bits most.
- let dat = _mm256_lddqu_si256(ptr as *const _);
-
- // unsigned comparison dat >= LOW
- //
- // `_mm256_max_epu8` creates a new vector by comparing vectors `dat` and `LOW`
- // and picks the max. values from each for all indices.
- // So if a byte in `dat` is <= 32, it'll be represented as 33
- // which is the smallest valid character.
- //
- // Then, we compare the new vector with `dat` for equality.
- //
- // `_mm256_cmpeq_epi8` returns a new vector where;
- // * matching bytes are set to 0xFF (all bits set),
- // * nonmatching bytes are set to 0 (no bits set).
- let low = _mm256_cmpeq_epi8(_mm256_max_epu8(dat, LOW), dat);
- // Similar to what we did before, but now invalid characters are set to 0xFF.
- let del = _mm256_cmpeq_epi8(dat, DEL);
-
- // We glue the both comparisons via `_mm256_andnot_si256`.
- //
- // Since the representation of truthiness differ in these comparisons,
- // we are in need of bitwise NOT to convert valid characters of `del`.
- let bit = _mm256_andnot_si256(del, low);
- // This creates a bitmask from the most significant bit of each byte.
- // Simply, we're converting a vector value to scalar value here.
- let res = _mm256_movemask_epi8(bit) as u32;
-
- // Count trailing zeros to find the first encountered invalid character.
- // Bitwise NOT is required once again to flip truthiness.
- // TODO: use .trailing_ones() once MSRV >= 1.46
- (!res).trailing_zeros() as usize
-}
-
-#[target_feature(enable = "avx2")]
-pub unsafe fn match_header_value_vectored(bytes: &mut Bytes) {
- while bytes.as_ref().len() >= 32 {
- let advance = match_header_value_char_32_avx(bytes.as_ref());
- bytes.advance(advance);
-
- if advance != 32 {
- return;
- }
- }
- // NOTE: use SWAR for <32B, more efficient than falling back to SSE4.2
- super::swar::match_header_value_vectored(bytes)
-}
-
-#[inline(always)]
-#[allow(non_snake_case)]
-#[allow(unused)]
-unsafe fn match_header_value_char_32_avx(buf: &[u8]) -> usize {
- debug_assert!(buf.len() >= 32);
-
- #[cfg(target_arch = "x86")]
- use core::arch::x86::*;
- #[cfg(target_arch = "x86_64")]
- use core::arch::x86_64::*;
-
- let ptr = buf.as_ptr();
-
- // %x09 %x20-%x7e %x80-%xff
- // Create a vector full of horizontal tab (\t) (0x09) characters.
- let TAB: __m256i = _mm256_set1_epi8(0x09);
- // Create a vector full of DEL (0x7f) characters.
- let DEL: __m256i = _mm256_set1_epi8(0x7f);
- // Create a vector full of space (0x20) characters.
- let LOW: __m256i = _mm256_set1_epi8(0x20);
-
- // Load a chunk of 32 bytes from `ptr` as a vector.
- let dat = _mm256_lddqu_si256(ptr as *const _);
-
- // unsigned comparison dat >= LOW
- //
- // Same as what we do in `match_url_char_32_avx`.
- // This time the lower threshold is set to space character though.
- let low = _mm256_cmpeq_epi8(_mm256_max_epu8(dat, LOW), dat);
- // Check if `dat` includes `TAB` characters.
- let tab = _mm256_cmpeq_epi8(dat, TAB);
- // Check if `dat` includes `DEL` characters.
- let del = _mm256_cmpeq_epi8(dat, DEL);
-
- // Combine all comparisons together, notice that we're also using OR
- // to connect `low` and `tab` but flip bits of `del`.
- //
- // In the end, this is simply:
- // ~del & (low | tab)
- let bit = _mm256_andnot_si256(del, _mm256_or_si256(low, tab));
- // This creates a bitmask from the most significant bit of each byte.
- // Creates a scalar value from vector value.
- let res = _mm256_movemask_epi8(bit) as u32;
-
- // Count trailing zeros to find the first encountered invalid character.
- // Bitwise NOT is required once again to flip truthiness.
- // TODO: use .trailing_ones() once MSRV >= 1.46
- (!res).trailing_zeros() as usize
-}
-
-#[test]
-fn avx2_code_matches_uri_chars_table() {
- if !is_x86_feature_detected!("avx2") {
- return;
- }
-
- #[allow(clippy::undocumented_unsafe_blocks)]
- unsafe {
- assert!(byte_is_allowed(b'_', match_uri_vectored));
-
- for (b, allowed) in crate::URI_MAP.iter().cloned().enumerate() {
- assert_eq!(
- byte_is_allowed(b as u8, match_uri_vectored), allowed,
- "byte_is_allowed({:?}) should be {:?}", b, allowed,
- );
- }
- }
-}
-
-#[test]
-fn avx2_code_matches_header_value_chars_table() {
- if !is_x86_feature_detected!("avx2") {
- return;
- }
-
- #[allow(clippy::undocumented_unsafe_blocks)]
- unsafe {
- assert!(byte_is_allowed(b'_', match_header_value_vectored));
-
- for (b, allowed) in crate::HEADER_VALUE_MAP.iter().cloned().enumerate() {
- assert_eq!(
- byte_is_allowed(b as u8, match_header_value_vectored), allowed,
- "byte_is_allowed({:?}) should be {:?}", b, allowed,
- );
- }
- }
-}
-
-#[cfg(test)]
-unsafe fn byte_is_allowed(byte: u8, f: unsafe fn(bytes: &mut Bytes<'_>)) -> bool {
- let slice = [
- b'_', b'_', b'_', b'_',
- b'_', b'_', b'_', b'_',
- b'_', b'_', b'_', b'_',
- b'_', b'_', b'_', b'_',
- b'_', b'_', b'_', b'_',
- b'_', b'_', b'_', b'_',
- b'_', b'_', byte, b'_',
- b'_', b'_', b'_', b'_',
- ];
- let mut bytes = Bytes::new(&slice);
-
- f(&mut bytes);
-
- match bytes.pos() {
- 32 => true,
- 26 => false,
- _ => unreachable!(),
- }
-}
diff --git a/vendor/httparse/src/simd/mod.rs b/vendor/httparse/src/simd/mod.rs
deleted file mode 100644
index 0e4493a5..00000000
--- a/vendor/httparse/src/simd/mod.rs
+++ /dev/null
@@ -1,153 +0,0 @@
-mod swar;
-
-#[cfg(not(all(
- httparse_simd,
- any(
- target_arch = "x86",
- target_arch = "x86_64",
- all(
- target_arch = "aarch64",
- httparse_simd_neon_intrinsics,
- )
- ),
-)))]
-pub use self::swar::*;
-
-#[cfg(all(
- httparse_simd,
- not(httparse_simd_target_feature_avx2),
- any(
- target_arch = "x86",
- target_arch = "x86_64",
- ),
-))]
-mod sse42;
-
-#[cfg(all(
- httparse_simd,
- any(
- httparse_simd_target_feature_avx2,
- not(httparse_simd_target_feature_sse42),
- ),
- any(
- target_arch = "x86",
- target_arch = "x86_64",
- ),
-))]
-mod avx2;
-
-#[cfg(all(
- httparse_simd,
- not(any(
- httparse_simd_target_feature_sse42,
- httparse_simd_target_feature_avx2,
- )),
- any(
- target_arch = "x86",
- target_arch = "x86_64",
- ),
-))]
-mod runtime;
-
-#[cfg(all(
- httparse_simd,
- not(any(
- httparse_simd_target_feature_sse42,
- httparse_simd_target_feature_avx2,
- )),
- any(
- target_arch = "x86",
- target_arch = "x86_64",
- ),
-))]
-pub use self::runtime::*;
-
-#[cfg(all(
- httparse_simd,
- httparse_simd_target_feature_sse42,
- not(httparse_simd_target_feature_avx2),
- any(
- target_arch = "x86",
- target_arch = "x86_64",
- ),
-))]
-mod sse42_compile_time {
- #[inline(always)]
- pub fn match_header_name_vectored(b: &mut crate::iter::Bytes<'_>) {
- super::swar::match_header_name_vectored(b);
- }
-
- #[inline(always)]
- pub fn match_uri_vectored(b: &mut crate::iter::Bytes<'_>) {
- // SAFETY: calls are guarded by a compile time feature check
- unsafe { crate::simd::sse42::match_uri_vectored(b) }
- }
-
- #[inline(always)]
- pub fn match_header_value_vectored(b: &mut crate::iter::Bytes<'_>) {
- // SAFETY: calls are guarded by a compile time feature check
- unsafe { crate::simd::sse42::match_header_value_vectored(b) }
- }
-}
-
-#[cfg(all(
- httparse_simd,
- httparse_simd_target_feature_sse42,
- not(httparse_simd_target_feature_avx2),
- any(
- target_arch = "x86",
- target_arch = "x86_64",
- ),
-))]
-pub use self::sse42_compile_time::*;
-
-#[cfg(all(
- httparse_simd,
- httparse_simd_target_feature_avx2,
- any(
- target_arch = "x86",
- target_arch = "x86_64",
- ),
-))]
-mod avx2_compile_time {
- #[inline(always)]
- pub fn match_header_name_vectored(b: &mut crate::iter::Bytes<'_>) {
- super::swar::match_header_name_vectored(b);
- }
-
- #[inline(always)]
- pub fn match_uri_vectored(b: &mut crate::iter::Bytes<'_>) {
- // SAFETY: calls are guarded by a compile time feature check
- unsafe { crate::simd::avx2::match_uri_vectored(b) }
- }
-
- #[inline(always)]
- pub fn match_header_value_vectored(b: &mut crate::iter::Bytes<'_>) {
- // SAFETY: calls are guarded by a compile time feature check
- unsafe { crate::simd::avx2::match_header_value_vectored(b) }
- }
-}
-
-#[cfg(all(
- httparse_simd,
- httparse_simd_target_feature_avx2,
- any(
- target_arch = "x86",
- target_arch = "x86_64",
- ),
-))]
-pub use self::avx2_compile_time::*;
-
-#[cfg(all(
- httparse_simd,
- target_arch = "aarch64",
- httparse_simd_neon_intrinsics,
-))]
-mod neon;
-
-#[cfg(all(
- httparse_simd,
- target_arch = "aarch64",
- httparse_simd_neon_intrinsics,
-))]
-pub use self::neon::*;
diff --git a/vendor/httparse/src/simd/neon.rs b/vendor/httparse/src/simd/neon.rs
deleted file mode 100644
index b059efb2..00000000
--- a/vendor/httparse/src/simd/neon.rs
+++ /dev/null
@@ -1,258 +0,0 @@
-use crate::iter::Bytes;
-use core::arch::aarch64::*;
-
-#[inline]
-pub fn match_header_name_vectored(bytes: &mut Bytes) {
- while bytes.as_ref().len() >= 16 {
- // SAFETY: ensured that there are at least 16 bytes remaining
- unsafe {
- let advance = match_header_name_char_16_neon(bytes.as_ref().as_ptr());
- bytes.advance(advance);
-
- if advance != 16 {
- return;
- }
- }
- }
- super::swar::match_header_name_vectored(bytes);
-}
-
-#[inline]
-pub fn match_header_value_vectored(bytes: &mut Bytes) {
- while bytes.as_ref().len() >= 16 {
- // SAFETY: ensured that there are at least 16 bytes remaining
- unsafe {
- let advance = match_header_value_char_16_neon(bytes.as_ref().as_ptr());
- bytes.advance(advance);
-
- if advance != 16 {
- return;
- }
- }
- }
- super::swar::match_header_value_vectored(bytes);
-}
-
-#[inline]
-pub fn match_uri_vectored(bytes: &mut Bytes) {
- while bytes.as_ref().len() >= 16 {
- // SAFETY: ensured that there are at least 16 bytes remaining
- unsafe {
- let advance = match_url_char_16_neon(bytes.as_ref().as_ptr());
- bytes.advance(advance);
-
- if advance != 16 {
- return;
- }
- }
- }
- super::swar::match_uri_vectored(bytes);
-}
-
-const fn bit_set(x: u8) -> bool {
- // Validates if a byte is a valid header name character
- // https://tools.ietf.org/html/rfc7230#section-3.2.6
- matches!(x, b'0'..=b'9' | b'a'..=b'z' | b'A'..=b'Z' | b'!' | b'#' | b'$' | b'%' | b'&' | b'\'' | b'*' | b'+' | b'-' | b'.' | b'^' | b'_' | b'`' | b'|' | b'~')
-}
-
-// A 256-bit bitmap, split into two halves
-// lower half contains bits whose higher nibble is <= 7
-// higher half contains bits whose higher nibble is >= 8
-const fn build_bitmap() -> ([u8; 16], [u8; 16]) {
- let mut bitmap_0_7 = [0u8; 16]; // 0x00..0x7F
- let mut bitmap_8_15 = [0u8; 16]; // 0x80..0xFF
- let mut i = 0;
- while i < 256 {
- if bit_set(i as u8) {
- // Nibbles
- let (lo, hi) = (i & 0x0F, i >> 4);
- if i < 128 {
- bitmap_0_7[lo] |= 1 << hi;
- } else {
- bitmap_8_15[lo] |= 1 << hi;
- }
- }
- i += 1;
- }
- (bitmap_0_7, bitmap_8_15)
-}
-
-const BITMAPS: ([u8; 16], [u8; 16]) = build_bitmap();
-
-// NOTE: adapted from 256-bit version, with upper 128-bit ops commented out
-#[inline]
-unsafe fn match_header_name_char_16_neon(ptr: *const u8) -> usize {
- let bitmaps = BITMAPS;
- // NOTE: ideally compile-time constants
- let (bitmap_0_7, _bitmap_8_15) = bitmaps;
- let bitmap_0_7 = vld1q_u8(bitmap_0_7.as_ptr());
- // let bitmap_8_15 = vld1q_u8(bitmap_8_15.as_ptr());
-
- // Initialize the bitmask_lookup.
- const BITMASK_LOOKUP_DATA: [u8; 16] =
- [1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128];
- let bitmask_lookup = vld1q_u8(BITMASK_LOOKUP_DATA.as_ptr());
-
- // Load 16 input bytes.
- let input = vld1q_u8(ptr);
-
- // Extract indices for row_0_7.
- let indices_0_7 = vandq_u8(input, vdupq_n_u8(0x8F)); // 0b1000_1111;
-
- // Extract indices for row_8_15.
- // let msb = vandq_u8(input, vdupq_n_u8(0x80));
- // let indices_8_15 = veorq_u8(indices_0_7, msb);
-
- // Fetch row_0_7 and row_8_15.
- let row_0_7 = vqtbl1q_u8(bitmap_0_7, indices_0_7);
- // let row_8_15 = vqtbl1q_u8(bitmap_8_15, indices_8_15);
-
- // Calculate a bitmask, i.e. (1 << hi_nibble % 8).
- let bitmask = vqtbl1q_u8(bitmask_lookup, vshrq_n_u8(input, 4));
-
- // Choose rows halves depending on higher nibbles.
- // let bitsets = vorrq_u8(row_0_7, row_8_15);
- let bitsets = row_0_7;
-
- // Finally check which bytes belong to the set.
- let tmp = vandq_u8(bitsets, bitmask);
- let result = vceqq_u8(tmp, bitmask);
-
- offsetz(result) as usize
-}
-
-#[inline]
-unsafe fn match_url_char_16_neon(ptr: *const u8) -> usize {
- let input = vld1q_u8(ptr);
-
- // Check that b'!' <= and b != 127
- let result = vcleq_u8(vdupq_n_u8(b'!'), input);
-
- // Disallow del
- let del = vceqq_u8(input, vdupq_n_u8(0x7F));
- let result = vbicq_u8(result, del);
-
- offsetz(result) as usize
-}
-
-#[inline]
-unsafe fn match_header_value_char_16_neon(ptr: *const u8) -> usize {
- let input = vld1q_u8(ptr);
-
- // Check that b' ' <= and b != 127 or b == 9
- let result = vcleq_u8(vdupq_n_u8(b' '), input);
-
- // Allow tab
- let tab = vceqq_u8(input, vdupq_n_u8(0x09));
- let result = vorrq_u8(result, tab);
-
- // Disallow del
- let del = vceqq_u8(input, vdupq_n_u8(0x7F));
- let result = vbicq_u8(result, del);
-
- offsetz(result) as usize
-}
-
-#[inline]
-unsafe fn offsetz(x: uint8x16_t) -> u32 {
- // NOT the vector since it's faster to operate with zeros instead
- offsetnz(vmvnq_u8(x))
-}
-
-#[inline]
-unsafe fn offsetnz(x: uint8x16_t) -> u32 {
- // Extract two u64
- let x = vreinterpretq_u64_u8(x);
- // Extract to general purpose registers to perform clz
- let low: u64 = vgetq_lane_u64::<0>(x);
- let high: u64 = vgetq_lane_u64::<1>(x);
-
- #[inline]
- fn clz(x: u64) -> u32 {
- // perf: rust will unroll this loop
- // and it's much faster than rbit + clz so voila
- for (i, b) in x.to_ne_bytes().iter().copied().enumerate() {
- if b != 0 {
- return i as u32;
- }
- }
- 8 // Technically not reachable since zero-guarded
- }
-
- if low != 0 {
- clz(low)
- } else if high != 0 {
- return 8 + clz(high);
- } else {
- return 16;
- }
-}
-
-#[test]
-fn neon_code_matches_uri_chars_table() {
- #[allow(clippy::undocumented_unsafe_blocks)]
- unsafe {
- assert!(byte_is_allowed(b'_', match_uri_vectored));
-
- for (b, allowed) in crate::URI_MAP.iter().cloned().enumerate() {
- assert_eq!(
- byte_is_allowed(b as u8, match_uri_vectored),
- allowed,
- "byte_is_allowed({:?}) should be {:?}",
- b,
- allowed,
- );
- }
- }
-}
-
-#[test]
-fn neon_code_matches_header_value_chars_table() {
- #[allow(clippy::undocumented_unsafe_blocks)]
- unsafe {
- assert!(byte_is_allowed(b'_', match_header_value_vectored));
-
- for (b, allowed) in crate::HEADER_VALUE_MAP.iter().cloned().enumerate() {
- assert_eq!(
- byte_is_allowed(b as u8, match_header_value_vectored),
- allowed,
- "byte_is_allowed({:?}) should be {:?}",
- b,
- allowed,
- );
- }
- }
-}
-
-#[test]
-fn neon_code_matches_header_name_chars_table() {
- #[allow(clippy::undocumented_unsafe_blocks)]
- unsafe {
- assert!(byte_is_allowed(b'_', match_header_name_vectored));
-
- for (b, allowed) in crate::TOKEN_MAP.iter().cloned().enumerate() {
- assert_eq!(
- byte_is_allowed(b as u8, match_header_name_vectored),
- allowed,
- "byte_is_allowed({:?}) should be {:?}",
- b,
- allowed,
- );
- }
- }
-}
-
-#[cfg(test)]
-unsafe fn byte_is_allowed(byte: u8, f: unsafe fn(bytes: &mut Bytes<'_>)) -> bool {
- let mut slice = [b'_'; 16];
- slice[10] = byte;
- let mut bytes = Bytes::new(&slice);
-
- f(&mut bytes);
-
- match bytes.pos() {
- 16 => true,
- 10 => false,
- x => panic!("unexpected pos: {}", x),
- }
-}
diff --git a/vendor/httparse/src/simd/runtime.rs b/vendor/httparse/src/simd/runtime.rs
deleted file mode 100644
index c523a921..00000000
--- a/vendor/httparse/src/simd/runtime.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-use std::sync::atomic::{AtomicU8, Ordering};
-use crate::iter::Bytes;
-use super::avx2;
-use super::sse42;
-
-const AVX2: u8 = 1;
-const SSE42: u8 = 2;
-const NOP: u8 = 3;
-
-fn detect_runtime_feature() -> u8 {
- if is_x86_feature_detected!("avx2") {
- AVX2
- } else if is_x86_feature_detected!("sse4.2") {
- SSE42
- } else {
- NOP
- }
-}
-
-static RUNTIME_FEATURE: AtomicU8 = AtomicU8::new(0);
-
-#[inline]
-fn get_runtime_feature() -> u8 {
- let mut feature = RUNTIME_FEATURE.load(Ordering::Relaxed);
- if feature == 0 {
- feature = detect_runtime_feature();
- RUNTIME_FEATURE.store(feature, Ordering::Relaxed);
- }
-
- feature
-}
-
-pub fn match_header_name_vectored(bytes: &mut Bytes) {
- super::swar::match_header_name_vectored(bytes);
-}
-
-pub fn match_uri_vectored(bytes: &mut Bytes) {
- // SAFETY: calls are guarded by a feature check
- unsafe {
- match get_runtime_feature() {
- AVX2 => avx2::match_uri_vectored(bytes),
- SSE42 => sse42::match_uri_vectored(bytes),
- _ /* NOP */ => super::swar::match_uri_vectored(bytes),
- }
- }
-}
-
-pub fn match_header_value_vectored(bytes: &mut Bytes) {
- // SAFETY: calls are guarded by a feature check
- unsafe {
- match get_runtime_feature() {
- AVX2 => avx2::match_header_value_vectored(bytes),
- SSE42 => sse42::match_header_value_vectored(bytes),
- _ /* NOP */ => super::swar::match_header_value_vectored(bytes),
- }
- }
-}
diff --git a/vendor/httparse/src/simd/sse42.rs b/vendor/httparse/src/simd/sse42.rs
deleted file mode 100644
index 0fabdfeb..00000000
--- a/vendor/httparse/src/simd/sse42.rs
+++ /dev/null
@@ -1,142 +0,0 @@
-use crate::iter::Bytes;
-
-#[target_feature(enable = "sse4.2")]
-pub unsafe fn match_uri_vectored(bytes: &mut Bytes) {
- while bytes.as_ref().len() >= 16 {
- let advance = match_url_char_16_sse(bytes.as_ref());
-
- bytes.advance(advance);
-
- if advance != 16 {
- return;
- }
- }
- super::swar::match_uri_vectored(bytes);
-}
-
-#[inline(always)]
-#[allow(non_snake_case)]
-unsafe fn match_url_char_16_sse(buf: &[u8]) -> usize {
- debug_assert!(buf.len() >= 16);
-
- #[cfg(target_arch = "x86")]
- use core::arch::x86::*;
- #[cfg(target_arch = "x86_64")]
- use core::arch::x86_64::*;
-
- let ptr = buf.as_ptr();
-
- // %x21-%x7e %x80-%xff
- let DEL: __m128i = _mm_set1_epi8(0x7f);
- let LOW: __m128i = _mm_set1_epi8(0x21);
-
- let dat = _mm_lddqu_si128(ptr as *const _);
- // unsigned comparison dat >= LOW
- let low = _mm_cmpeq_epi8(_mm_max_epu8(dat, LOW), dat);
- let del = _mm_cmpeq_epi8(dat, DEL);
- let bit = _mm_andnot_si128(del, low);
- let res = _mm_movemask_epi8(bit) as u16;
-
- // TODO: use .trailing_ones() once MSRV >= 1.46
- (!res).trailing_zeros() as usize
-}
-
-#[target_feature(enable = "sse4.2")]
-pub unsafe fn match_header_value_vectored(bytes: &mut Bytes) {
- while bytes.as_ref().len() >= 16 {
- let advance = match_header_value_char_16_sse(bytes.as_ref());
- bytes.advance(advance);
-
- if advance != 16 {
- return;
- }
- }
- super::swar::match_header_value_vectored(bytes);
-}
-
-#[inline(always)]
-#[allow(non_snake_case)]
-unsafe fn match_header_value_char_16_sse(buf: &[u8]) -> usize {
- debug_assert!(buf.len() >= 16);
-
- #[cfg(target_arch = "x86")]
- use core::arch::x86::*;
- #[cfg(target_arch = "x86_64")]
- use core::arch::x86_64::*;
-
- let ptr = buf.as_ptr();
-
- // %x09 %x20-%x7e %x80-%xff
- let TAB: __m128i = _mm_set1_epi8(0x09);
- let DEL: __m128i = _mm_set1_epi8(0x7f);
- let LOW: __m128i = _mm_set1_epi8(0x20);
-
- let dat = _mm_lddqu_si128(ptr as *const _);
- // unsigned comparison dat >= LOW
- let low = _mm_cmpeq_epi8(_mm_max_epu8(dat, LOW), dat);
- let tab = _mm_cmpeq_epi8(dat, TAB);
- let del = _mm_cmpeq_epi8(dat, DEL);
- let bit = _mm_andnot_si128(del, _mm_or_si128(low, tab));
- let res = _mm_movemask_epi8(bit) as u16;
-
- // TODO: use .trailing_ones() once MSRV >= 1.46
- (!res).trailing_zeros() as usize
-}
-
-#[test]
-fn sse_code_matches_uri_chars_table() {
- if !is_x86_feature_detected!("sse4.2") {
- return;
- }
-
- #[allow(clippy::undocumented_unsafe_blocks)]
- unsafe {
- assert!(byte_is_allowed(b'_', match_uri_vectored));
-
- for (b, allowed) in crate::URI_MAP.iter().cloned().enumerate() {
- assert_eq!(
- byte_is_allowed(b as u8, match_uri_vectored), allowed,
- "byte_is_allowed({:?}) should be {:?}", b, allowed,
- );
- }
- }
-}
-
-#[test]
-fn sse_code_matches_header_value_chars_table() {
- if !is_x86_feature_detected!("sse4.2") {
- return;
- }
-
- #[allow(clippy::undocumented_unsafe_blocks)]
- unsafe {
- assert!(byte_is_allowed(b'_', match_header_value_vectored));
-
- for (b, allowed) in crate::HEADER_VALUE_MAP.iter().cloned().enumerate() {
- assert_eq!(
- byte_is_allowed(b as u8, match_header_value_vectored), allowed,
- "byte_is_allowed({:?}) should be {:?}", b, allowed,
- );
- }
- }
-}
-
-#[allow(clippy::missing_safety_doc)]
-#[cfg(test)]
-unsafe fn byte_is_allowed(byte: u8, f: unsafe fn(bytes: &mut Bytes<'_>)) -> bool {
- let slice = [
- b'_', b'_', b'_', b'_',
- b'_', b'_', b'_', b'_',
- b'_', b'_', byte, b'_',
- b'_', b'_', b'_', b'_',
- ];
- let mut bytes = Bytes::new(&slice);
-
- f(&mut bytes);
-
- match bytes.pos() {
- 16 => true,
- 10 => false,
- _ => unreachable!(),
- }
-}
diff --git a/vendor/httparse/src/simd/swar.rs b/vendor/httparse/src/simd/swar.rs
deleted file mode 100644
index e1028d05..00000000
--- a/vendor/httparse/src/simd/swar.rs
+++ /dev/null
@@ -1,235 +0,0 @@
-/// SWAR: SIMD Within A Register
-/// SIMD validator backend that validates register-sized chunks of data at a time.
-use crate::{is_header_name_token, is_header_value_token, is_uri_token, Bytes};
-
-// Adapt block-size to match native register size, i.e: 32bit => 4, 64bit => 8
-const BLOCK_SIZE: usize = core::mem::size_of::<usize>();
-type ByteBlock = [u8; BLOCK_SIZE];
-
-#[inline]
-pub fn match_uri_vectored(bytes: &mut Bytes) {
- loop {
- if let Some(bytes8) = bytes.peek_n::<ByteBlock>(BLOCK_SIZE) {
- let n = match_uri_char_8_swar(bytes8);
- // SAFETY: using peek_n to retrieve the bytes ensures that there are at least n more bytes
- // in `bytes`, so calling `advance(n)` is safe.
- unsafe {
- bytes.advance(n);
- }
- if n == BLOCK_SIZE {
- continue;
- }
- }
- if let Some(b) = bytes.peek() {
- if is_uri_token(b) {
- // SAFETY: using peek to retrieve the byte ensures that there is at least 1 more byte
- // in bytes, so calling advance is safe.
- unsafe {
- bytes.advance(1);
- }
- continue;
- }
- }
- break;
- }
-}
-
-#[inline]
-pub fn match_header_value_vectored(bytes: &mut Bytes) {
- loop {
- if let Some(bytes8) = bytes.peek_n::<ByteBlock>(BLOCK_SIZE) {
- let n = match_header_value_char_8_swar(bytes8);
- // SAFETY: using peek_n to retrieve the bytes ensures that there are at least n more bytes
- // in `bytes`, so calling `advance(n)` is safe.
- unsafe {
- bytes.advance(n);
- }
- if n == BLOCK_SIZE {
- continue;
- }
- }
- if let Some(b) = bytes.peek() {
- if is_header_value_token(b) {
- // SAFETY: using peek to retrieve the byte ensures that there is at least 1 more byte
- // in bytes, so calling advance is safe.
- unsafe {
- bytes.advance(1);
- }
- continue;
- }
- }
- break;
- }
-}
-
-#[inline]
-pub fn match_header_name_vectored(bytes: &mut Bytes) {
- while let Some(block) = bytes.peek_n::<ByteBlock>(BLOCK_SIZE) {
- let n = match_block(is_header_name_token, block);
- // SAFETY: using peek_n to retrieve the bytes ensures that there are at least n more bytes
- // in `bytes`, so calling `advance(n)` is safe.
- unsafe {
- bytes.advance(n);
- }
- if n != BLOCK_SIZE {
- return;
- }
- }
- // SAFETY: match_tail processes at most the remaining data in `bytes`. advances `bytes` to the
- // end, but no further.
- unsafe { bytes.advance(match_tail(is_header_name_token, bytes.as_ref())) };
-}
-
-// Matches "tail", i.e: when we have <BLOCK_SIZE bytes in the buffer, should be uncommon
-#[cold]
-#[inline]
-fn match_tail(f: impl Fn(u8) -> bool, bytes: &[u8]) -> usize {
- for (i, &b) in bytes.iter().enumerate() {
- if !f(b) {
- return i;
- }
- }
- bytes.len()
-}
-
-// Naive fallback block matcher
-#[inline(always)]
-fn match_block(f: impl Fn(u8) -> bool, block: ByteBlock) -> usize {
- for (i, &b) in block.iter().enumerate() {
- if !f(b) {
- return i;
- }
- }
- BLOCK_SIZE
-}
-
-// A const alternative to u64::from_ne_bytes to avoid bumping MSRV (1.36 => 1.44)
-// creates a u64 whose bytes are each equal to b
-const fn uniform_block(b: u8) -> usize {
- (b as u64 * 0x01_01_01_01_01_01_01_01 /* [1_u8; 8] */) as usize
-}
-
-// A byte-wise range-check on an entire word/block,
-// ensuring all bytes in the word satisfy `33 <= (x != 127) <= 255`
-#[inline]
-fn match_uri_char_8_swar(block: ByteBlock) -> usize {
- // 33 <= (x != 127) <= 255
- const M: u8 = 0x21;
- // uniform block full of exclamation mark (!) (33).
- const BM: usize = uniform_block(M);
- // uniform block full of 1.
- const ONE: usize = uniform_block(0x01);
- // uniform block full of DEL (127).
- const DEL: usize = uniform_block(0x7f);
- // uniform block full of 128.
- const M128: usize = uniform_block(128);
-
- let x = usize::from_ne_bytes(block); // Really just a transmute
- let lt = x.wrapping_sub(BM) & !x; // <= m
-
- let xor_del = x ^ DEL;
- let eq_del = xor_del.wrapping_sub(ONE) & !xor_del; // == DEL
-
- offsetnz((lt | eq_del) & M128)
-}
-
-// A byte-wise range-check on an entire word/block,
-// ensuring all bytes in the word satisfy `32 <= (x != 127) <= 255`
-#[inline]
-fn match_header_value_char_8_swar(block: ByteBlock) -> usize {
- // 32 <= (x != 127) <= 255
- const M: u8 = 0x20;
- // uniform block full of exclamation mark (!) (33).
- const BM: usize = uniform_block(M);
- // uniform block full of 1.
- const ONE: usize = uniform_block(0x01);
- // uniform block full of DEL (127).
- const DEL: usize = uniform_block(0x7f);
- // uniform block full of 128.
- const M128: usize = uniform_block(128);
-
- let x = usize::from_ne_bytes(block); // Really just a transmute
- let lt = x.wrapping_sub(BM) & !x; // <= m
-
- let xor_del = x ^ DEL;
- let eq_del = xor_del.wrapping_sub(ONE) & !xor_del; // == DEL
-
- offsetnz((lt | eq_del) & M128)
-}
-
-/// Check block to find offset of first non-zero byte
-// NOTE: Curiously `block.trailing_zeros() >> 3` appears to be slower, maybe revisit
-#[inline]
-fn offsetnz(block: usize) -> usize {
- // fast path optimistic case (common for long valid sequences)
- if block == 0 {
- return BLOCK_SIZE;
- }
-
- // perf: rust will unroll this loop
- for (i, b) in block.to_ne_bytes().iter().copied().enumerate() {
- if b != 0 {
- return i;
- }
- }
- unreachable!()
-}
-
-#[test]
-fn test_is_header_value_block() {
- let is_header_value_block = |b| match_header_value_char_8_swar(b) == BLOCK_SIZE;
-
- // 0..32 => false
- for b in 0..32_u8 {
- assert!(!is_header_value_block([b; BLOCK_SIZE]), "b={}", b);
- }
- // 32..=126 => true
- for b in 32..=126_u8 {
- assert!(is_header_value_block([b; BLOCK_SIZE]), "b={}", b);
- }
- // 127 => false
- assert!(!is_header_value_block([b'\x7F'; BLOCK_SIZE]), "b={}", b'\x7F');
- // 128..=255 => true
- for b in 128..=255_u8 {
- assert!(is_header_value_block([b; BLOCK_SIZE]), "b={}", b);
- }
-
-
- #[cfg(target_pointer_width = "64")]
- {
- // A few sanity checks on non-uniform bytes for safe-measure
- assert!(!is_header_value_block(*b"foo.com\n"));
- assert!(!is_header_value_block(*b"o.com\r\nU"));
- }
-}
-
-#[test]
-fn test_is_uri_block() {
- let is_uri_block = |b| match_uri_char_8_swar(b) == BLOCK_SIZE;
-
- // 0..33 => false
- for b in 0..33_u8 {
- assert!(!is_uri_block([b; BLOCK_SIZE]), "b={}", b);
- }
- // 33..=126 => true
- for b in 33..=126_u8 {
- assert!(is_uri_block([b; BLOCK_SIZE]), "b={}", b);
- }
- // 127 => false
- assert!(!is_uri_block([b'\x7F'; BLOCK_SIZE]), "b={}", b'\x7F');
- // 128..=255 => true
- for b in 128..=255_u8 {
- assert!(is_uri_block([b; BLOCK_SIZE]), "b={}", b);
- }
-}
-
-#[test]
-fn test_offsetnz() {
- let seq = [0_u8; BLOCK_SIZE];
- for i in 0..BLOCK_SIZE {
- let mut seq = seq;
- seq[i] = 1;
- let x = usize::from_ne_bytes(seq);
- assert_eq!(offsetnz(x), i);
- }
-}
diff --git a/vendor/httparse/tests/uri.rs b/vendor/httparse/tests/uri.rs
deleted file mode 100644
index e0ceab47..00000000
--- a/vendor/httparse/tests/uri.rs
+++ /dev/null
@@ -1,3692 +0,0 @@
-
-use httparse::{Error, Request, Status, EMPTY_HEADER};
-
-const NUM_OF_HEADERS: usize = 4;
-
-macro_rules! req {
- ($name:ident, $buf:expr, |$arg:ident| $body:expr) => (
- req! {$name, $buf, Ok(Status::Complete($buf.len())), |$arg| $body }
- );
- ($name:ident, $buf:expr, $len:expr, |$arg:ident| $body:expr) => (
- #[test]
- fn $name() {
- let mut headers = [EMPTY_HEADER; NUM_OF_HEADERS];
- let mut req = Request::new(&mut headers[..]);
- let status = req.parse($buf.as_ref());
- assert_eq!(status, $len);
- closure(req);
-
- fn closure($arg: Request<'_, '_>) {
- $body
- }
- }
- )
-}
-
-req! {
- urltest_001,
- b"GET /bar;par?b HTTP/1.1\r\nHost: foo\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/bar;par?b");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo");
- }
-}
-
-
-req! {
- urltest_002,
- b"GET /x HTTP/1.1\r\nHost: test\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/x");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"test");
- }
-}
-
-
-req! {
- urltest_003,
- b"GET /x HTTP/1.1\r\nHost: test\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/x");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"test");
- }
-}
-
-
-req! {
- urltest_004,
- b"GET /foo/foo.com HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/foo.com");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_005,
- b"GET /foo/:foo.com HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/:foo.com");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_006,
- b"GET /foo/foo.com HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/foo.com");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_007,
- b"GET foo.com HTTP/1.1\r\nHost: \r\n\r\n",
- Err(Error::Token),
- |_r| {}
-}
-
-
-req! {
- urltest_008,
- b"GET /%20b%20?%20d%20 HTTP/1.1\r\nHost: f\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/%20b%20?%20d%20");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"f");
- }
-}
-
-
-req! {
- urltest_009,
- b"GET x x HTTP/1.1\r\nHost: \r\n\r\n",
- Err(Error::Version),
- |_r| {}
-}
-
-
-req! {
- urltest_010,
- b"GET /c HTTP/1.1\r\nHost: f\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/c");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"f");
- }
-}
-
-
-req! {
- urltest_011,
- b"GET /c HTTP/1.1\r\nHost: f\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/c");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"f");
- }
-}
-
-
-req! {
- urltest_012,
- b"GET /c HTTP/1.1\r\nHost: f\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/c");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"f");
- }
-}
-
-
-req! {
- urltest_013,
- b"GET /c HTTP/1.1\r\nHost: f\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/c");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"f");
- }
-}
-
-
-req! {
- urltest_014,
- b"GET /c HTTP/1.1\r\nHost: f\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/c");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"f");
- }
-}
-
-
-req! {
- urltest_015,
- b"GET /foo/bar HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_016,
- b"GET /foo/bar HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_017,
- b"GET /foo/:foo.com/ HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/:foo.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_018,
- b"GET /foo/:foo.com/ HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/:foo.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_019,
- b"GET /foo/: HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/:");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_020,
- b"GET /foo/:a HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/:a");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_021,
- b"GET /foo/:/ HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_022,
- b"GET /foo/:/ HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_023,
- b"GET /foo/: HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/:");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_024,
- b"GET /foo/bar HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_025,
- b"GET /foo/bar HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_026,
- b"GET /foo/bar HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_027,
- b"GET /foo/bar HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_028,
- b"GET /foo/bar HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_029,
- b"GET /foo/:23 HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/:23");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_030,
- b"GET /:23 HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/:23");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_031,
- b"GET /foo/:: HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/::");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_032,
- b"GET /foo/::23 HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/::23");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_033,
- b"GET /d HTTP/1.1\r\nHost: c\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/d");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"c");
- }
-}
-
-
-req! {
- urltest_034,
- b"GET /foo/:@c:29 HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/:@c:29");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_035,
- b"GET //@ HTTP/1.1\r\nHost: foo.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "//@");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo.com");
- }
-}
-
-
-req! {
- urltest_036,
- b"GET /b:c/d@foo.com/ HTTP/1.1\r\nHost: a\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/b:c/d@foo.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"a");
- }
-}
-
-
-req! {
- urltest_037,
- b"GET /bar.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/bar.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_038,
- b"GET /////// HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "///////");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_039,
- b"GET ///////bar.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "///////bar.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_040,
- b"GET //:///// HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "//://///");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_041,
- b"GET /foo HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_042,
- b"GET /bar HTTP/1.1\r\nHost: foo\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo");
- }
-}
-
-
-req! {
- urltest_043,
- b"GET /path;a??e HTTP/1.1\r\nHost: foo\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/path;a??e");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo");
- }
-}
-
-
-req! {
- urltest_044,
- b"GET /abcd?efgh?ijkl HTTP/1.1\r\nHost: foo\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/abcd?efgh?ijkl");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo");
- }
-}
-
-
-req! {
- urltest_045,
- b"GET /abcd HTTP/1.1\r\nHost: foo\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/abcd");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo");
- }
-}
-
-
-req! {
- urltest_046,
- b"GET /foo/[61:24:74]:98 HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/[61:24:74]:98");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_047,
- b"GET /foo/[61:27]/:foo HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/[61:27]/:foo");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_048,
- b"GET /example.com/ HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_049,
- b"GET /example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_050,
- b"GET /example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_051,
- b"GET /example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_052,
- b"GET /example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_053,
- b"GET /example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_054,
- b"GET /example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_055,
- b"GET /foo/example.com/ HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_056,
- b"GET example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_057,
- b"GET example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_058,
- b"GET example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_059,
- b"GET example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_060,
- b"GET example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_061,
- b"GET /a/b/c HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/a/b/c");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_062,
- b"GET /a/%20/c HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/a/%20/c");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_063,
- b"GET /a%2fc HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/a%2fc");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_064,
- b"GET /a/%2f/c HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/a/%2f/c");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_065,
- b"GET /foo/bar HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_066,
- b"GET text/html,test HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "text/html,test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_067,
- b"GET 1234567890 HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "1234567890");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_068,
- b"GET /c:/foo/bar.html HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/c:/foo/bar.html");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_069,
- b"GET /c:////foo/bar.html HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/c:////foo/bar.html");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_070,
- b"GET /C:/foo/bar HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_071,
- b"GET /C:/foo/bar HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_072,
- b"GET /C:/foo/bar HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_073,
- b"GET /file HTTP/1.1\r\nHost: server\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/file");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"server");
- }
-}
-
-
-req! {
- urltest_074,
- b"GET /file HTTP/1.1\r\nHost: server\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/file");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"server");
- }
-}
-
-
-req! {
- urltest_075,
- b"GET /file HTTP/1.1\r\nHost: server\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/file");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"server");
- }
-}
-
-
-req! {
- urltest_076,
- b"GET /foo/bar.txt HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar.txt");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_077,
- b"GET /home/me HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/home/me");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_078,
- b"GET /test HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_079,
- b"GET /test HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_080,
- b"GET /tmp/mock/test HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/tmp/mock/test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_081,
- b"GET /tmp/mock/test HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/tmp/mock/test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_082,
- b"GET /foo HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_083,
- b"GET /.foo HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/.foo");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_084,
- b"GET /foo/ HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_085,
- b"GET /foo/ HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_086,
- b"GET /foo/ HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_087,
- b"GET /foo/ HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_088,
- b"GET /foo/..bar HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/..bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_089,
- b"GET /foo/ton HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/ton");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_090,
- b"GET /a HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/a");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_091,
- b"GET /ton HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/ton");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_092,
- b"GET /foo/ HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_093,
- b"GET /foo/%2e%2 HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/%2e%2");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_094,
- b"GET /%2e.bar HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/%2e.bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_095,
- b"GET // HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "//");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_096,
- b"GET /foo/ HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_097,
- b"GET /foo/bar/ HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_098,
- b"GET /foo HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_099,
- b"GET /%20foo HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/%20foo");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_100,
- b"GET /foo% HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo%");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_101,
- b"GET /foo%2 HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo%2");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_102,
- b"GET /foo%2zbar HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo%2zbar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_103,
- b"GET /foo%2%C3%82%C2%A9zbar HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo%2%C3%82%C2%A9zbar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_104,
- b"GET /foo%41%7a HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo%41%7a");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_105,
- b"GET /foo%C2%91%91 HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo%C2%91%91");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_106,
- b"GET /foo%00%51 HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo%00%51");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_107,
- b"GET /(%28:%3A%29) HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/(%28:%3A%29)");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_108,
- b"GET /%3A%3a%3C%3c HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/%3A%3a%3C%3c");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_109,
- b"GET /foobar HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foobar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_110,
- b"GET //foo//bar HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "//foo//bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_111,
- b"GET /%7Ffp3%3Eju%3Dduvgw%3Dd HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/%7Ffp3%3Eju%3Dduvgw%3Dd");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_112,
- b"GET /@asdf%40 HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/@asdf%40");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_113,
- b"GET /%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_114,
- b"GET /%E2%80%A5/foo HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/%E2%80%A5/foo");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_115,
- b"GET /%EF%BB%BF/foo HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/%EF%BB%BF/foo");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_116,
- b"GET /%E2%80%AE/foo/%E2%80%AD/bar HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/%E2%80%AE/foo/%E2%80%AD/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_117,
- b"GET /foo?bar=baz HTTP/1.1\r\nHost: www.google.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo?bar=baz");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"www.google.com");
- }
-}
-
-
-req! {
- urltest_118,
- b"GET /foo?bar=baz HTTP/1.1\r\nHost: www.google.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo?bar=baz");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"www.google.com");
- }
-}
-
-
-req! {
- urltest_119,
- b"GET test HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_120,
- b"GET /foo%2Ehtml HTTP/1.1\r\nHost: www\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo%2Ehtml");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"www");
- }
-}
-
-
-req! {
- urltest_121,
- b"GET /foo/html HTTP/1.1\r\nHost: www\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/html");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"www");
- }
-}
-
-
-req! {
- urltest_122,
- b"GET /foo HTTP/1.1\r\nHost: www.google.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"www.google.com");
- }
-}
-
-
-req! {
- urltest_123,
- b"GET /example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_124,
- b"GET /example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_125,
- b"GET /example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_126,
- b"GET /example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_127,
- b"GET /example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_128,
- b"GET /example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_129,
- b"GET example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_130,
- b"GET example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_131,
- b"GET example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_132,
- b"GET example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_133,
- b"GET example.com/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "example.com/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_134,
- b"GET /test.txt HTTP/1.1\r\nHost: www.example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test.txt");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"www.example.com");
- }
-}
-
-
-req! {
- urltest_135,
- b"GET /test.txt HTTP/1.1\r\nHost: www.example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test.txt");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"www.example.com");
- }
-}
-
-
-req! {
- urltest_136,
- b"GET /test.txt HTTP/1.1\r\nHost: www.example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test.txt");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"www.example.com");
- }
-}
-
-
-req! {
- urltest_137,
- b"GET /test.txt HTTP/1.1\r\nHost: www.example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test.txt");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"www.example.com");
- }
-}
-
-
-req! {
- urltest_138,
- b"GET /aaa/test.txt HTTP/1.1\r\nHost: www.example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/aaa/test.txt");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"www.example.com");
- }
-}
-
-
-req! {
- urltest_139,
- b"GET /test.txt HTTP/1.1\r\nHost: www.example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test.txt");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"www.example.com");
- }
-}
-
-
-req! {
- urltest_140,
- b"GET /%E4%B8%AD/test.txt HTTP/1.1\r\nHost: www.example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/%E4%B8%AD/test.txt");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"www.example.com");
- }
-}
-
-
-req! {
- urltest_141,
- b"GET /... HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/...");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_142,
- b"GET /a HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/a");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_143,
- b"GET /%EF%BF%BD?%EF%BF%BD HTTP/1.1\r\nHost: x\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/%EF%BF%BD?%EF%BF%BD");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"x");
- }
-}
-
-
-req! {
- urltest_144,
- b"GET /bar HTTP/1.1\r\nHost: example.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.com");
- }
-}
-
-
-req! {
- urltest_145,
- b"GET test HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_146,
- b"GET x@x.com HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "x@x.com");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_147,
- b"GET , HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), ",");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_148,
- b"GET blank HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "blank");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_149,
- b"GET test?test HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "test?test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_150,
- b"GET /%60%7B%7D?`{} HTTP/1.1\r\nHost: h\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/%60%7B%7D?`{}");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"h");
- }
-
-}
-
-
-req! {
- urltest_151,
- b"GET /?%27 HTTP/1.1\r\nHost: host\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/?%27");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"host");
- }
-}
-
-
-req! {
- urltest_152,
- b"GET /?' HTTP/1.1\r\nHost: host\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/?'");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"host");
- }
-}
-
-
-req! {
- urltest_153,
- b"GET /some/path HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/some/path");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_154,
- b"GET /smth HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/smth");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_155,
- b"GET /some/path HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/some/path");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_156,
- b"GET /pa/i HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/pa/i");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_157,
- b"GET /i HTTP/1.1\r\nHost: ho\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/i");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"ho");
- }
-}
-
-
-req! {
- urltest_158,
- b"GET /pa/i HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/pa/i");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_159,
- b"GET /i HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/i");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_160,
- b"GET /i HTTP/1.1\r\nHost: ho\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/i");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"ho");
- }
-}
-
-
-req! {
- urltest_161,
- b"GET /i HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/i");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_162,
- b"GET /i HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/i");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_163,
- b"GET /i HTTP/1.1\r\nHost: ho\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/i");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"ho");
- }
-}
-
-
-req! {
- urltest_164,
- b"GET /i HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/i");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_165,
- b"GET /pa/pa?i HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/pa/pa?i");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_166,
- b"GET /pa?i HTTP/1.1\r\nHost: ho\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/pa?i");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"ho");
- }
-}
-
-
-req! {
- urltest_167,
- b"GET /pa/pa?i HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/pa/pa?i");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_168,
- b"GET sd HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "sd");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_169,
- b"GET sd/sd HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "sd/sd");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_170,
- b"GET /pa/pa HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/pa/pa");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_171,
- b"GET /pa HTTP/1.1\r\nHost: ho\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/pa");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"ho");
- }
-}
-
-
-req! {
- urltest_172,
- b"GET /pa/pa HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/pa/pa");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_173,
- b"GET /x HTTP/1.1\r\nHost: %C3%B1\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/x");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"%C3%B1");
- }
-}
-
-
-req! {
- urltest_174,
- b"GET \\.\\./ HTTP/1.1\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "\\.\\./");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 0);
- }
-}
-
-
-req! {
- urltest_175,
- b"GET :a@example.net HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), ":a@example.net");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_176,
- b"GET %NBD HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "%NBD");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_177,
- b"GET %1G HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "%1G");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_178,
- b"GET /relative_import.html HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/relative_import.html");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"127.0.0.1");
- }
-}
-
-
-req! {
- urltest_179,
- b"GET /?foo=%7B%22abc%22 HTTP/1.1\r\nHost: facebook.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/?foo=%7B%22abc%22");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"facebook.com");
- }
-}
-
-
-req! {
- urltest_180,
- b"GET /jqueryui@1.2.3 HTTP/1.1\r\nHost: localhost\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/jqueryui@1.2.3");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"localhost");
- }
-}
-
-
-req! {
- urltest_181,
- b"GET /path?query HTTP/1.1\r\nHost: host\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/path?query");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"host");
- }
-}
-
-
-req! {
- urltest_182,
- b"GET /foo/bar?a=b&c=d HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar?a=b&c=d");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_183,
- b"GET /foo/bar??a=b&c=d HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar??a=b&c=d");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_184,
- b"GET /foo/bar HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_185,
- b"GET /baz?qux HTTP/1.1\r\nHost: foo.bar\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/baz?qux");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo.bar");
- }
-}
-
-
-req! {
- urltest_186,
- b"GET /baz?qux HTTP/1.1\r\nHost: foo.bar\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/baz?qux");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo.bar");
- }
-}
-
-
-req! {
- urltest_187,
- b"GET /baz?qux HTTP/1.1\r\nHost: foo.bar\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/baz?qux");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo.bar");
- }
-}
-
-
-req! {
- urltest_188,
- b"GET /baz?qux HTTP/1.1\r\nHost: foo.bar\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/baz?qux");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo.bar");
- }
-}
-
-
-req! {
- urltest_189,
- b"GET /baz?qux HTTP/1.1\r\nHost: foo.bar\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/baz?qux");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foo.bar");
- }
-}
-
-
-req! {
- urltest_190,
- b"GET /C%3A/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C%3A/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_191,
- b"GET /C%7C/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C%7C/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_192,
- b"GET /C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/pix/submit.gif HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/pix/submit.gif");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_193,
- b"GET /C:/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_194,
- b"GET /C:/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_195,
- b"GET /d: HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/d:");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_196,
- b"GET /d:/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/d:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_197,
- b"GET /test?test HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_198,
- b"GET /test?test HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_199,
- b"GET /test?x HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?x");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_200,
- b"GET /test?x HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?x");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_201,
- b"GET /test?test HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_202,
- b"GET /test?test HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_203,
- b"GET /?fox HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/?fox");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_204,
- b"GET /localhost//cat HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/localhost//cat");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_205,
- b"GET /localhost//cat HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/localhost//cat");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_206,
- b"GET /mouse HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/mouse");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_207,
- b"GET /pig HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/pig");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_208,
- b"GET /pig HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/pig");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_209,
- b"GET /pig HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/pig");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_210,
- b"GET /localhost//pig HTTP/1.1\r\nHost: lion\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/localhost//pig");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"lion");
- }
-}
-
-
-req! {
- urltest_211,
- b"GET /rooibos HTTP/1.1\r\nHost: tea\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/rooibos");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"tea");
- }
-}
-
-
-req! {
- urltest_212,
- b"GET /?chai HTTP/1.1\r\nHost: tea\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/?chai");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"tea");
- }
-}
-
-
-req! {
- urltest_213,
- b"GET /C: HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_214,
- b"GET /C: HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_215,
- b"GET /C: HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_216,
- b"GET /C:/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_217,
- b"GET /C:/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_218,
- b"GET /C:/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_219,
- b"GET /dir/C HTTP/1.1\r\nHost: host\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/dir/C");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"host");
- }
-}
-
-
-req! {
- urltest_220,
- b"GET /dir/C|a HTTP/1.1\r\nHost: host\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/dir/C|a");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"host");
- }
-}
-
-
-req! {
- urltest_221,
- b"GET /c:/foo/bar HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/c:/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_222,
- b"GET /c:/foo/bar HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/c:/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_223,
- b"GET /c:/foo/bar HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/c:/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_224,
- b"GET /c:/foo/bar HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/c:/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_225,
- b"GET /C:/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_226,
- b"GET /C:/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_227,
- b"GET /C:/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_228,
- b"GET /C:/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_229,
- b"GET /C:/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/C:/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_230,
- b"GET /?q=v HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/?q=v");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_231,
- b"GET ?x HTTP/1.1\r\nHost: %C3%B1\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "?x");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"%C3%B1");
- }
-}
-
-
-req! {
- urltest_232,
- b"GET ?x HTTP/1.1\r\nHost: %C3%B1\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "?x");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"%C3%B1");
- }
-}
-
-
-req! {
- urltest_233,
- b"GET // HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "//");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_234,
- b"GET //x/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "//x/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_235,
- b"GET /someconfig;mode=netascii HTTP/1.1\r\nHost: foobar.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/someconfig;mode=netascii");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"foobar.com");
- }
-}
-
-
-req! {
- urltest_236,
- b"GET /Index.ut2 HTTP/1.1\r\nHost: 10.10.10.10\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/Index.ut2");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"10.10.10.10");
- }
-}
-
-
-req! {
- urltest_237,
- b"GET /0?baz=bam&qux=baz HTTP/1.1\r\nHost: somehost\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/0?baz=bam&qux=baz");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"somehost");
- }
-}
-
-
-req! {
- urltest_238,
- b"GET /sup HTTP/1.1\r\nHost: host\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/sup");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"host");
- }
-}
-
-
-req! {
- urltest_239,
- b"GET /foo/bar.git HTTP/1.1\r\nHost: github.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar.git");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"github.com");
- }
-}
-
-
-req! {
- urltest_240,
- b"GET /channel?passwd HTTP/1.1\r\nHost: myserver.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/channel?passwd");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"myserver.com");
- }
-}
-
-
-req! {
- urltest_241,
- b"GET /foo.bar.org?type=TXT HTTP/1.1\r\nHost: fw.example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo.bar.org?type=TXT");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"fw.example.org");
- }
-}
-
-
-req! {
- urltest_242,
- b"GET /ou=People,o=JNDITutorial HTTP/1.1\r\nHost: localhost\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/ou=People,o=JNDITutorial");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"localhost");
- }
-}
-
-
-req! {
- urltest_243,
- b"GET /foo/bar HTTP/1.1\r\nHost: github.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"github.com");
- }
-}
-
-
-req! {
- urltest_244,
- b"GET ietf:rfc:2648 HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "ietf:rfc:2648");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_245,
- b"GET joe@example.org,2001:foo/bar HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "joe@example.org,2001:foo/bar");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_246,
- b"GET /path HTTP/1.1\r\nHost: H%4fSt\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/path");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"H%4fSt");
- }
-}
-
-
-req! {
- urltest_247,
- b"GET https://example.com:443/ HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "https://example.com:443/");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_248,
- b"GET d3958f5c-0777-0845-9dcf-2cb28783acaf HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "d3958f5c-0777-0845-9dcf-2cb28783acaf");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_249,
- b"GET /test?%22 HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?%22");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_250,
- b"GET /test HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_251,
- b"GET /test?%3C HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?%3C");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_252,
- b"GET /test?%3E HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?%3E");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_253,
- b"GET /test?%E2%8C%A3 HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?%E2%8C%A3");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_254,
- b"GET /test?%23%23 HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?%23%23");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_255,
- b"GET /test?%GH HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?%GH");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_256,
- b"GET /test?a HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?a");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_257,
- b"GET /test?a HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?a");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_258,
- b"GET /test-a-colon-slash.html HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test-a-colon-slash.html");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_259,
- b"GET /test-a-colon-slash-slash.html HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test-a-colon-slash-slash.html");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_260,
- b"GET /test-a-colon-slash-b.html HTTP/1.1\r\nHost: \r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test-a-colon-slash-b.html");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"");
- }
-}
-
-
-req! {
- urltest_261,
- b"GET /test-a-colon-slash-slash-b.html HTTP/1.1\r\nHost: b\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test-a-colon-slash-slash-b.html");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"b");
- }
-}
-
-
-req! {
- urltest_262,
- b"GET /test?a HTTP/1.1\r\nHost: example.org\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/test?a");
- assert_eq!(req.version.unwrap(), 1);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"example.org");
- }
-}
-
-
-req! {
- urltest_nvidia,
- b"GET /nvidia_web_services/controller.gfeclientcontent.php/com.nvidia.services.GFEClientContent.getShieldReady/{\"gcV\":\"2.2.2.0\",\"dID\":\"1341\",\"osC\":\"6.20\",\"is6\":\"1\",\"lg\":\"1033\",\"GFPV\":\"389.08\",\"isO\":\"1\",\"sM\":\"16777216\"} HTTP/1.0\r\nHost: gfwsl.geforce.com\r\n\r\n",
- |req| {
- assert_eq!(req.method.unwrap(), "GET");
- assert_eq!(req.path.unwrap(), "/nvidia_web_services/controller.gfeclientcontent.php/com.nvidia.services.GFEClientContent.getShieldReady/{\"gcV\":\"2.2.2.0\",\"dID\":\"1341\",\"osC\":\"6.20\",\"is6\":\"1\",\"lg\":\"1033\",\"GFPV\":\"389.08\",\"isO\":\"1\",\"sM\":\"16777216\"}");
- assert_eq!(req.version.unwrap(), 0);
- assert_eq!(req.headers.len(), 1);
- assert_eq!(req.headers[0].name, "Host");
- assert_eq!(req.headers[0].value, b"gfwsl.geforce.com");
- }
-}