diff --git a/components/net/fetch/headers.rs b/components/net/fetch/headers.rs index d306cda0057..e113ac0ed20 100644 --- a/components/net/fetch/headers.rs +++ b/components/net/fetch/headers.rs @@ -2,162 +2,15 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::iter::Peekable; -use std::str::Chars; - use headers::HeaderMap; -use net_traits::fetch::headers::get_value_from_header_list; - -/// -const HTTP_TAB_OR_SPACE: &[char] = &['\u{0009}', '\u{0020}']; +use net_traits::fetch::headers::get_decode_and_split_header_name; /// pub fn determine_nosniff(headers: &HeaderMap) -> bool { - let values = get_header_value_as_list("x-content-type-options", headers); + let values = get_decode_and_split_header_name("x-content-type-options", headers); match values { None => false, Some(values) => !values.is_empty() && values[0].eq_ignore_ascii_case("nosniff"), } } - -/// -fn get_header_value_as_list(name: &str, headers: &HeaderMap) -> Option> { - fn char_is_not_quote_or_comma(c: char) -> bool { - c != '\u{0022}' && c != '\u{002C}' - } - - // Step 1 - let initial_value = get_value_from_header_list(name, headers); - - if let Some(input) = initial_value { - // https://fetch.spec.whatwg.org/#header-value-get-decode-and-split - // Step 1 - let input = input.into_iter().map(char::from).collect::(); - - // Step 2 - let mut position = input.chars().peekable(); - - // Step 3 - let mut values: Vec = vec![]; - - // Step 4 - let mut value = String::new(); - - // Step 5 - while position.peek().is_some() { - // Step 5.1 - value += &*collect_sequence(&mut position, char_is_not_quote_or_comma); - - // Step 5.2 - if let Some(&ch) = position.peek() { - if ch == '\u{0022}' { - // Step 5.2.1.1 - value += &*collect_http_quoted_string(&mut position, false); - - // Step 5.2.1.2 - if position.peek().is_some() { - continue; - } - } else { - // ch == '\u{002C}' - - // Step 5.2.2.2 - position.next(); - } - } - - // Step 5.3 - value = value.trim_matches(HTTP_TAB_OR_SPACE).to_string(); - - // Step 5.4 - values.push(value); - - // Step 5.5 - value = String::new(); - } - - return Some(values); - } - - // Step 2 - None -} - -/// -fn collect_sequence(position: &mut Peekable, condition: F) -> String -where - F: Fn(char) -> bool, -{ - // Step 1 - let mut result = String::new(); - - // Step 2 - while let Some(&ch) = position.peek() { - if !condition(ch) { - break; - } - result.push(ch); - position.next(); - } - - // Step 3 - result -} - -/// -fn collect_http_quoted_string(position: &mut Peekable, extract_value: bool) -> String { - fn char_is_not_quote_or_backslash(c: char) -> bool { - c != '\u{0022}' && c != '\u{005C}' - } - - // Step 2 - // We will store the 'extracted value' or the raw value - let mut value = String::new(); - - // Step 3, 4 - let should_be_quote = position.next(); - if let Some(ch) = should_be_quote { - if !extract_value { - value.push(ch) - } - } - - // Step 5 - loop { - // Step 5.1 - value += &*collect_sequence(position, char_is_not_quote_or_backslash); - - // Step 5.2 - if position.peek().is_none() { - break; - } - - // Step 5.3, 5.4 - let quote_or_backslash = position.next().unwrap(); - if !extract_value { - value.push(quote_or_backslash); - } - - if quote_or_backslash == '\u{005C}' { - if let Some(ch) = position.next() { - value.push(ch); - } else { - // Step 5.5.1 - if extract_value { - value.push('\u{005C}'); - } - break; - } - } else { - // Step 5.6.1 - // assert quote_or_backslash is a quote - - // Step 5.6.2 - break; - } - } - - // Step 6, 7 - value -} diff --git a/components/script/dom/headers.rs b/components/script/dom/headers.rs index 7bf032693ee..5d076db3f70 100644 --- a/components/script/dom/headers.rs +++ b/components/script/dom/headers.rs @@ -9,7 +9,9 @@ use data_url::mime::Mime as DataUrlMime; use dom_struct::dom_struct; use http::header::{HeaderMap as HyperHeaders, HeaderName, HeaderValue}; use js::rust::HandleObject; -use net_traits::fetch::headers::get_value_from_header_list; +use net_traits::fetch::headers::{ + get_decode_and_split_header_value, get_value_from_header_list, is_forbidden_method, +}; use net_traits::request::is_cors_safelisted_request_header; use crate::dom::bindings::cell::DomRefCell; @@ -85,12 +87,15 @@ impl HeadersMethods for Headers { // Step 2 // https://fetch.spec.whatwg.org/#headers-validate let (mut valid_name, valid_value) = validate_name_and_value(name, value)?; + valid_name = valid_name.to_lowercase(); if self.guard.get() == Guard::Immutable { return Err(Error::Type("Guard is immutable".to_string())); } - if self.guard.get() == Guard::Request && is_forbidden_header_name(&valid_name) { + if self.guard.get() == Guard::Request && + is_forbidden_request_header(&valid_name, &valid_value) + { return Ok(()); } if self.guard.get() == Guard::Response && is_forbidden_response_header(&valid_name) { @@ -141,13 +146,18 @@ impl HeadersMethods for Headers { // https://fetch.spec.whatwg.org/#dom-headers-delete fn Delete(&self, name: ByteString) -> ErrorResult { // Step 1 - let valid_name = validate_name(name)?; + let (mut valid_name, valid_value) = validate_name_and_value(name, ByteString::new(vec![]))?; + + valid_name = valid_name.to_lowercase(); + // Step 2 if self.guard.get() == Guard::Immutable { return Err(Error::Type("Guard is immutable".to_string())); } // Step 3 - if self.guard.get() == Guard::Request && is_forbidden_header_name(&valid_name) { + if self.guard.get() == Guard::Request && + is_forbidden_request_header(&valid_name, &valid_value) + { return Ok(()); } // Step 4 @@ -205,7 +215,9 @@ impl HeadersMethods for Headers { return Err(Error::Type("Guard is immutable".to_string())); } // Step 4 - if self.guard.get() == Guard::Request && is_forbidden_header_name(&valid_name) { + if self.guard.get() == Guard::Request && + is_forbidden_request_header(&valid_name, &valid_value) + { return Ok(()); } // Step 5 @@ -358,14 +370,12 @@ impl Iterable for Headers { } } -// https://fetch.spec.whatwg.org/#forbidden-response-header-name -fn is_forbidden_response_header(name: &str) -> bool { - matches!(name, "set-cookie" | "set-cookie2") -} - -// https://fetch.spec.whatwg.org/#forbidden-header-name -pub fn is_forbidden_header_name(name: &str) -> bool { - let disallowed_headers = [ +/// This function will internally convert `name` to lowercase for matching, so explicitly converting +/// before calling is not necessary +/// +/// +pub fn is_forbidden_request_header(name: &str, value: &[u8]) -> bool { + let forbidden_header_names = [ "accept-charset", "accept-encoding", "access-control-request-headers", @@ -386,14 +396,61 @@ pub fn is_forbidden_header_name(name: &str) -> bool { "transfer-encoding", "upgrade", "via", + // This list is defined in the fetch spec, however the draft spec for private-network-access + // proposes this additional forbidden name, which is currently included in WPT tests. See: + // https://wicg.github.io/private-network-access/#forbidden-header-names + "access-control-request-private-network", ]; - let disallowed_header_prefixes = ["sec-", "proxy-"]; + // Step 1: If name is a byte-case-insensitive match for one of (forbidden_header_names), return + // true + let lowercase_name = name.to_lowercase(); - disallowed_headers.iter().any(|header| *header == name) || - disallowed_header_prefixes + if forbidden_header_names + .iter() + .any(|header| *header == lowercase_name.as_str()) + { + return true; + } + + let forbidden_header_prefixes = ["sec-", "proxy-"]; + + // Step 2: If name when byte-lowercased starts with `proxy-` or `sec-`, then return true. + if forbidden_header_prefixes + .iter() + .any(|prefix| lowercase_name.starts_with(prefix)) + { + return true; + } + + let potentially_forbidden_header_names = [ + "x-http-method", + "x-http-method-override", + "x-method-override", + ]; + + // Step 3: If name is a byte-case-insensitive match for one of (potentially_forbidden_header_names) + if potentially_forbidden_header_names + .iter() + .any(|header| *header == lowercase_name) + { + // Step 3.1: Let parsedValues be the result of getting, decoding, and splitting value. + let parsed_values = get_decode_and_split_header_value(value.to_vec()); + + // Step 3.2: For each method of parsedValues: if the isomorphic encoding of method is a + // forbidden method, then return true. + return parsed_values .iter() - .any(|prefix| name.starts_with(prefix)) + .any(|s| is_forbidden_method(s.as_bytes())); + } + + // Step 4: Return false. + false +} + +// https://fetch.spec.whatwg.org/#forbidden-response-header-name +fn is_forbidden_response_header(name: &str) -> bool { + matches!(name, "set-cookie" | "set-cookie2") } // There is some unresolved confusion over the definition of a name and a value. diff --git a/components/script/dom/request.rs b/components/script/dom/request.rs index 5736311e942..cdfb50b014f 100644 --- a/components/script/dom/request.rs +++ b/components/script/dom/request.rs @@ -13,6 +13,7 @@ use http::method::InvalidMethod; use http::Method as HttpMethod; use js::jsapi::JSObject; use js::rust::HandleObject; +use net_traits::fetch::headers::is_forbidden_method; use net_traits::request::{ CacheMode as NetTraitsRequestCache, CredentialsMode as NetTraitsRequestCredentials, Destination as NetTraitsRequestDestination, Origin, RedirectMode as NetTraitsRequestRedirect, @@ -503,14 +504,6 @@ fn is_method(m: &ByteString) -> bool { m.as_str().is_some() } -// https://fetch.spec.whatwg.org/#forbidden-method -fn is_forbidden_method(m: &ByteString) -> bool { - matches!( - m.to_lower().as_str(), - Some("connect") | Some("trace") | Some("track") - ) -} - // https://fetch.spec.whatwg.org/#cors-safelisted-method fn is_cors_safelisted_method(m: &HttpMethod) -> bool { m == HttpMethod::GET || m == HttpMethod::HEAD || m == HttpMethod::POST diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index e8c41c08cb3..ab08b3dc86b 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -59,7 +59,7 @@ use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLD use crate::dom::event::{Event, EventBubbles, EventCancelable}; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; -use crate::dom::headers::{extract_mime_type, is_forbidden_header_name}; +use crate::dom::headers::{extract_mime_type, is_forbidden_request_header}; use crate::dom::node::Node; use crate::dom::performanceresourcetiming::InitiatorType; use crate::dom::progressevent::ProgressEvent; @@ -460,41 +460,37 @@ impl XMLHttpRequestMethods for XMLHttpRequest { /// fn SetRequestHeader(&self, name: ByteString, value: ByteString) -> ErrorResult { - // Step 1, 2 + // Step 1: If this’s state is not opened, then throw an "InvalidStateError" DOMException. + // Step 2: If this’s send() flag is set, then throw an "InvalidStateError" DOMException. if self.ready_state.get() != XMLHttpRequestState::Opened || self.send_flag.get() { return Err(Error::InvalidState); } - // Step 3 + // Step 3: Normalize value. let value = trim_http_whitespace(&value); - // Step 4 + // Step 4: If name is not a header name or value is not a header value, then throw a + // "SyntaxError" DOMException. if !is_token(&name) || !is_field_value(value) { return Err(Error::Syntax); } - let name_lower = name.to_lower(); - let name_str = match name_lower.as_str() { - Some(s) => { - // Step 5 - // Disallowed headers and header prefixes: - // https://fetch.spec.whatwg.org/#forbidden-header-name - if is_forbidden_header_name(s) { - return Ok(()); - } else { - s - } - }, - None => unreachable!(), - }; + + let name_str = name.as_str().ok_or(Error::Syntax)?; + + // Step 5: If (name, value) is a forbidden request-header, then return. + if is_forbidden_request_header(name_str, &value) { + return Ok(()); + } debug!( "SetRequestHeader: name={:?}, value={:?}", - name.as_str(), + name_str, str::from_utf8(value).ok() ); let mut headers = self.request_headers.borrow_mut(); - // Step 6 + // Step 6: Combine (name, value) in this’s author request headers. + // https://fetch.spec.whatwg.org/#concept-header-list-combine let value = match headers.get(name_str).map(HeaderValue::as_bytes) { Some(raw) => { let mut buf = raw.to_vec(); diff --git a/components/shared/net/fetch/headers.rs b/components/shared/net/fetch/headers.rs index 14caf03eea8..0e1508c5d3e 100644 --- a/components/shared/net/fetch/headers.rs +++ b/components/shared/net/fetch/headers.rs @@ -2,17 +2,185 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use std::iter::Peekable; +use std::str::Chars; + use headers::HeaderMap; +/// +const HTTP_TAB_OR_SPACE: &[char] = &['\u{0009}', '\u{0020}']; + /// pub fn get_value_from_header_list(name: &str, headers: &HeaderMap) -> Option> { let values = headers.get_all(name).iter().map(|val| val.as_bytes()); - // Step 1 + // Step 1: If list does not contain name, then return null. if values.size_hint() == (0, Some(0)) { return None; } - // Step 2 + // Step 2: Return the values of all headers in list whose name is a byte-case-insensitive match + // for name, separated from each other by 0x2C 0x20, in order. Some(values.collect::>().join(&[0x2C, 0x20][..])) } + +/// +pub fn is_forbidden_method(method: &[u8]) -> bool { + matches!( + method.to_ascii_lowercase().as_slice(), + b"connect" | b"trace" | b"track" + ) +} + +/// +pub fn get_decode_and_split_header_name(name: &str, headers: &HeaderMap) -> Option> { + // Step 1: Let value be the result of getting name from list. + // Step 2: If value is null, then return null. + // Step 3: Return the result of getting, decoding, and splitting value. + get_value_from_header_list(name, headers).map(|value| get_decode_and_split_header_value(value)) +} + +/// +pub fn get_decode_and_split_header_value(value: Vec) -> Vec { + fn char_is_not_quote_or_comma(c: char) -> bool { + c != '\u{0022}' && c != '\u{002C}' + } + + // Step 1: Let input be the result of isomorphic decoding value. + let input = value.into_iter().map(char::from).collect::(); + + // Step 2: Let position be a position variable for input, initially pointing at the start of + // input. + let mut position = input.chars().peekable(); + + // Step 3: Let values be a list of strings, initially « ». + let mut values: Vec = vec![]; + + // Step 4: Let temporaryValue be the empty string. + let mut temporary_value = String::new(); + + // Step 5: While true: + while position.peek().is_some() { + // Step 5.1: Append the result of collecting a sequence of code points that are not U+0022 + // (") or U+002C (,) from input, given position, to temporaryValue. + temporary_value += &*collect_sequence(&mut position, char_is_not_quote_or_comma); + + // Step 5.2: If position is not past the end of input and the code point at position within + // input is U+0022 ("): + if let Some(&ch) = position.peek() { + if ch == '\u{0022}' { + // Step 5.2.1: Append the result of collecting an HTTP quoted string from input, + // given position, to temporaryValue. + temporary_value += &*collect_http_quoted_string(&mut position, false); + + // Step 5.2.2: If position is not past the end of input, then continue. + if position.peek().is_some() { + continue; + } + } else { + // Step 5.2.2: If position is not past the end of input, then continue. + position.next(); + } + } + + // Step 5.3: Remove all HTTP tab or space from the start and end of temporaryValue. + temporary_value = temporary_value.trim_matches(HTTP_TAB_OR_SPACE).to_string(); + + // Step 5.4: Append temporaryValue to values. + values.push(temporary_value); + + // Step 5.5: Set temporaryValue to the empty string. + temporary_value = String::new(); + } + + return values; +} + +/// +fn collect_sequence(position: &mut Peekable, condition: F) -> String +where + F: Fn(char) -> bool, +{ + // Step 1: Let result be the empty string. + let mut result = String::new(); + + // Step 2: While position doesn’t point past the end of input and the code point at position + // within input meets the condition condition: + while let Some(&ch) = position.peek() { + if !condition(ch) { + break; + } + + // Step 2.1: Append that code point to the end of result. + result.push(ch); + + // Step 2.2: Advance position by 1. + position.next(); + } + + // Step 3: Return result. + result +} + +/// +fn collect_http_quoted_string(position: &mut Peekable, extract_value: bool) -> String { + fn char_is_not_quote_or_backslash(c: char) -> bool { + c != '\u{0022}' && c != '\u{005C}' + } + + // Step 2: let value be the empty string + // We will store the 'extracted value' or the raw value + let mut value = String::new(); + + // Step 3, 4 + let should_be_quote = position.next(); + if let Some(ch) = should_be_quote { + if !extract_value { + value.push(ch) + } + } + + // Step 5: While true: + loop { + // Step 5.1: Append the result of collecting a sequence of code points that are not U+0022 + // (") or U+005C (\) from input, given position, to value. + value += &*collect_sequence(position, char_is_not_quote_or_backslash); + + // Step 5.2: If position is past the end of input, then break. + if position.peek().is_none() { + break; + } + + // Step 5.3: Let quoteOrBackslash be the code point at position within input. + // Step 5.4: Advance position by 1. + let quote_or_backslash = position.next().unwrap(); + + if !extract_value { + value.push(quote_or_backslash); + } + + // Step 5.5: If quoteOrBackslash is U+005C (\), then: + if quote_or_backslash == '\u{005C}' { + if let Some(ch) = position.next() { + // Step 5.5.2: Append the code point at position within input to value. + value.push(ch); + } else { + // Step 5.5.1: If position is past the end of input, then append U+005C (\) to value and break. + if extract_value { + value.push('\u{005C}'); + } + + break; + } + } else { + // Step 5.6.1: Assert quote_or_backslash is a quote + assert_eq!(quote_or_backslash, '\u{0022}'); + + // Step 5.6.2: break + break; + } + } + + // Step 6, 7 + value +} diff --git a/tests/wpt/meta-legacy-layout/fetch/api/basic/request-private-network-headers.tentative.any.js.ini b/tests/wpt/meta-legacy-layout/fetch/api/basic/request-private-network-headers.tentative.any.js.ini index 76e46d3d30d..2c93eeb4fc0 100644 --- a/tests/wpt/meta-legacy-layout/fetch/api/basic/request-private-network-headers.tentative.any.js.ini +++ b/tests/wpt/meta-legacy-layout/fetch/api/basic/request-private-network-headers.tentative.any.js.ini @@ -1,21 +1,9 @@ [request-private-network-headers.tentative.any.worker.html] - [Access-Control-Request-Private-Network is a forbidden request header] - expected: FAIL - - [Adding invalid request header "Access-Control-Request-Private-Network: KO"] - expected: FAIL - [request-private-network-headers.tentative.any.sharedworker.html] expected: ERROR [request-private-network-headers.tentative.any.html] - [Access-Control-Request-Private-Network is a forbidden request header] - expected: FAIL - - [Adding invalid request header "Access-Control-Request-Private-Network: KO"] - expected: FAIL - [request-private-network-headers.tentative.any.serviceworker.html] expected: ERROR diff --git a/tests/wpt/meta/fetch/api/basic/request-forbidden-headers.any.js.ini b/tests/wpt/meta/fetch/api/basic/request-forbidden-headers.any.js.ini index 88c14114e79..667f77d71e5 100644 --- a/tests/wpt/meta/fetch/api/basic/request-forbidden-headers.any.js.ini +++ b/tests/wpt/meta/fetch/api/basic/request-forbidden-headers.any.js.ini @@ -1,267 +1,5 @@ -[request-forbidden-headers.any.worker.html] - [header x-http-method-override is forbidden to use value TRACE] - expected: FAIL - - [header x-http-method is forbidden to use value TRACE] - expected: FAIL - - [header x-method-override is forbidden to use value TRACE] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value TRACE] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value TRACE] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value TRACE] - expected: FAIL - - [header x-http-method-override is forbidden to use value TRACK] - expected: FAIL - - [header x-http-method is forbidden to use value TRACK] - expected: FAIL - - [header x-method-override is forbidden to use value TRACK] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value TRACK] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value TRACK] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value TRACK] - expected: FAIL - - [header x-http-method-override is forbidden to use value CONNECT] - expected: FAIL - - [header x-http-method is forbidden to use value CONNECT] - expected: FAIL - - [header x-method-override is forbidden to use value CONNECT] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value CONNECT] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value CONNECT] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value CONNECT] - expected: FAIL - - [header x-http-method-override is forbidden to use value trace] - expected: FAIL - - [header x-http-method is forbidden to use value trace] - expected: FAIL - - [header x-method-override is forbidden to use value trace] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value trace] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value trace] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value trace] - expected: FAIL - - [header x-http-method-override is forbidden to use value track] - expected: FAIL - - [header x-http-method is forbidden to use value track] - expected: FAIL - - [header x-method-override is forbidden to use value track] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value track] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value track] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value track] - expected: FAIL - - [header x-http-method-override is forbidden to use value connect] - expected: FAIL - - [header x-http-method is forbidden to use value connect] - expected: FAIL - - [header x-method-override is forbidden to use value connect] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value connect] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value connect] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value connect] - expected: FAIL - - [header x-http-method-override is forbidden to use value trace,] - expected: FAIL - - [header x-http-method is forbidden to use value trace,] - expected: FAIL - - [header x-method-override is forbidden to use value trace,] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value trace,] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value trace,] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value trace,] - expected: FAIL - - [Access-Control-Request-Private-Network is a forbidden request header] - expected: FAIL - - [request-forbidden-headers.any.sharedworker.html] expected: ERROR -[request-forbidden-headers.any.html] - [header x-http-method-override is forbidden to use value TRACE] - expected: FAIL - - [header x-http-method is forbidden to use value TRACE] - expected: FAIL - - [header x-method-override is forbidden to use value TRACE] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value TRACE] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value TRACE] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value TRACE] - expected: FAIL - - [header x-http-method-override is forbidden to use value TRACK] - expected: FAIL - - [header x-http-method is forbidden to use value TRACK] - expected: FAIL - - [header x-method-override is forbidden to use value TRACK] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value TRACK] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value TRACK] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value TRACK] - expected: FAIL - - [header x-http-method-override is forbidden to use value CONNECT] - expected: FAIL - - [header x-http-method is forbidden to use value CONNECT] - expected: FAIL - - [header x-method-override is forbidden to use value CONNECT] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value CONNECT] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value CONNECT] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value CONNECT] - expected: FAIL - - [header x-http-method-override is forbidden to use value trace] - expected: FAIL - - [header x-http-method is forbidden to use value trace] - expected: FAIL - - [header x-method-override is forbidden to use value trace] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value trace] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value trace] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value trace] - expected: FAIL - - [header x-http-method-override is forbidden to use value track] - expected: FAIL - - [header x-http-method is forbidden to use value track] - expected: FAIL - - [header x-method-override is forbidden to use value track] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value track] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value track] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value track] - expected: FAIL - - [header x-http-method-override is forbidden to use value connect] - expected: FAIL - - [header x-http-method is forbidden to use value connect] - expected: FAIL - - [header x-method-override is forbidden to use value connect] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value connect] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value connect] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value connect] - expected: FAIL - - [header x-http-method-override is forbidden to use value trace,] - expected: FAIL - - [header x-http-method is forbidden to use value trace,] - expected: FAIL - - [header x-method-override is forbidden to use value trace,] - expected: FAIL - - [header X-HTTP-METHOD-OVERRIDE is forbidden to use value trace,] - expected: FAIL - - [header X-HTTP-METHOD is forbidden to use value trace,] - expected: FAIL - - [header X-METHOD-OVERRIDE is forbidden to use value trace,] - expected: FAIL - - [Access-Control-Request-Private-Network is a forbidden request header] - expected: FAIL - - [request-forbidden-headers.any.serviceworker.html] expected: ERROR diff --git a/tests/wpt/meta/fetch/api/basic/request-private-network-headers.tentative.any.js.ini b/tests/wpt/meta/fetch/api/basic/request-private-network-headers.tentative.any.js.ini index 2a7b7f92e92..659b5574d54 100644 --- a/tests/wpt/meta/fetch/api/basic/request-private-network-headers.tentative.any.js.ini +++ b/tests/wpt/meta/fetch/api/basic/request-private-network-headers.tentative.any.js.ini @@ -1,21 +1,9 @@ [request-private-network-headers.tentative.any.worker.html] - [Access-Control-Request-Private-Network is a forbidden request header] - expected: FAIL - - [Adding invalid request header "Access-Control-Request-Private-Network: KO"] - expected: FAIL - [request-private-network-headers.tentative.any.serviceworker.html] expected: ERROR [request-private-network-headers.tentative.any.html] - [Access-Control-Request-Private-Network is a forbidden request header] - expected: FAIL - - [Adding invalid request header "Access-Control-Request-Private-Network: KO"] - expected: FAIL - [request-private-network-headers.tentative.any.sharedworker.html] expected: ERROR