diff --git a/moli-fetch/src/headers.rs b/moli-fetch/src/headers.rs index edbb00320a..aa9bfc202c 100644 --- a/moli-fetch/src/headers.rs +++ b/moli-fetch/src/headers.rs @@ -89,12 +89,22 @@ pub fn is_forbidden_request_header_override_value(name: &str, value: &str) -> bo ) { return false; } - // Fetch's "get, decode, and split" keeps quoted strings intact, including - // their quotes, so commas and method names inside them are ordinary data. + split_http_header_list(value).any(|method| { + matches!( + method.to_ascii_uppercase().as_str(), + "CONNECT" | "TRACE" | "TRACK" + ) + }) +} + +/// Fetch's "get, decode, and split" list splitting, after combining and +/// decoding the header fields. Quotes and escapes are preserved, so commas +/// and tokens inside a quoted string cannot become separate list members. +pub fn split_http_header_list(value: &str) -> impl Iterator { let mut quoted = false; let mut escaped = false; value - .split(|character| { + .split(move |character| { if escaped { escaped = false; false @@ -108,15 +118,7 @@ pub fn is_forbidden_request_header_override_value(name: &str, value: &str) -> bo character == ',' && !quoted } }) - .any(|method| { - matches!( - method - .trim_matches(is_http_whitespace) - .to_ascii_uppercase() - .as_str(), - "CONNECT" | "TRACE" | "TRACK" - ) - }) + .map(|member| member.trim_matches(is_http_whitespace)) } pub fn is_no_cors_safelisted_request_header(name: &str, value: &str) -> bool { diff --git a/moli-fetch/src/lib.rs b/moli-fetch/src/lib.rs index aa593b25d7..8f3543cda1 100644 --- a/moli-fetch/src/lib.rs +++ b/moli-fetch/src/lib.rs @@ -50,6 +50,7 @@ pub use headers::{ is_cors_safelisted_request_range, is_cors_unsafe_request_header_byte, is_forbidden_request_header_name, is_forbidden_request_header_override_value, is_forbidden_response_header_name, is_no_cors_safelisted_request_header, + split_http_header_list, }; pub use moli_cookie_jar::SharedBrowserCookieStore as SharedCookieStore; pub use moli_curl::websocket::CurlWebSocketConnector;