From cc7b1c508aea6c9b916f1250f779b8617f385cd7 Mon Sep 17 00:00:00 2001 From: Jeena Lee Date: Wed, 17 Aug 2016 15:03:46 -0700 Subject: [PATCH] Include "content-type" in cors safelisted request headers. This commit allows headers with "content-type" name to be classified as valid header name, depending on its value according to [the Fetch spec](https://fetch.spec.whatwg.org/#cors-safelisted-request-header). As a result of this change, more request web platform tests pass, whose expected test results are updated with this commit. --- components/script/dom/headers.rs | 46 ++++++++++++++----- .../api/request/request-headers.html.ini | 18 -------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/components/script/dom/headers.rs b/components/script/dom/headers.rs index cb3b4d13e48..6fa4e0249c8 100644 --- a/components/script/dom/headers.rs +++ b/components/script/dom/headers.rs @@ -12,8 +12,10 @@ use dom::bindings::js::Root; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::{ByteString, is_token}; use hyper::header::Headers as HyperHeaders; +use mime::{Mime, TopLevel, SubLevel}; use std::cell::Cell; use std::result::Result; +use std::str; #[dom_struct] pub struct Headers { @@ -72,7 +74,7 @@ impl HeadersMethods for Headers { return Ok(()); } // Step 5 - if self.guard.get() == Guard::RequestNoCors && !is_cors_safelisted_request_header(&valid_name) { + if self.guard.get() == Guard::RequestNoCors && !is_cors_safelisted_request_header(&valid_name, &valid_value) { return Ok(()); } // Step 6 @@ -103,9 +105,12 @@ impl HeadersMethods for Headers { return Ok(()); } // Step 4 - if self.guard.get() == Guard::RequestNoCors && !is_cors_safelisted_request_header(&valid_name) { - return Ok(()); - } + // TODO: Requires clarification from the Fetch spec: + // ... https://github.com/whatwg/fetch/issues/372 + if self.guard.get() == Guard::RequestNoCors && + !is_cors_safelisted_request_header(&valid_name, &b"invalid".to_vec()) { + return Ok(()); + } // Step 5 if self.guard.get() == Guard::Response && is_forbidden_response_header(&valid_name) { return Ok(()); @@ -148,7 +153,7 @@ impl HeadersMethods for Headers { return Ok(()); } // Step 5 - if self.guard.get() == Guard::RequestNoCors && !is_cors_safelisted_request_header(&valid_name) { + if self.guard.get() == Guard::RequestNoCors && !is_cors_safelisted_request_header(&valid_name, &valid_value) { return Ok(()); } // Step 6 @@ -220,18 +225,35 @@ impl Headers { } } -// TODO -// "Content-Type" once parsed, the value should be -// `application/x-www-form-urlencoded`, `multipart/form-data`, -// or `text/plain`. -// "DPR", "Downlink", "Save-Data", "Viewport-Width", "Width": -// once parsed, the value should not be failure. +fn is_cors_safelisted_request_content_type(value: &[u8]) -> bool { + let value_string = if let Ok(s) = str::from_utf8(value) { + s + } else { + return false; + }; + let value_mime_result: Result = value_string.parse(); + match value_mime_result { + Err(_) => false, + Ok(value_mime) => { + match value_mime { + Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, _) | + Mime(TopLevel::Multipart, SubLevel::FormData, _) | + Mime(TopLevel::Text, SubLevel::Plain, _) => true, + _ => false, + } + } + } +} + +// TODO: "DPR", "Downlink", "Save-Data", "Viewport-Width", "Width": +// ... once parsed, the value should not be failure. // https://fetch.spec.whatwg.org/#cors-safelisted-request-header -fn is_cors_safelisted_request_header(name: &str) -> bool { +fn is_cors_safelisted_request_header(name: &str, value: &[u8]) -> bool { match name { "accept" | "accept-language" | "content-language" => true, + "content-type" => is_cors_safelisted_request_content_type(value), _ => false, } } diff --git a/tests/wpt/metadata/fetch/api/request/request-headers.html.ini b/tests/wpt/metadata/fetch/api/request/request-headers.html.ini index b63c0f7c6d3..199c41344cf 100644 --- a/tests/wpt/metadata/fetch/api/request/request-headers.html.ini +++ b/tests/wpt/metadata/fetch/api/request/request-headers.html.ini @@ -1,23 +1,5 @@ [request-headers.html] type: testharness - [Adding valid no-cors request header "content-type: application/x-www-form-urlencoded"] - expected: FAIL - - [Adding valid no-cors request header "content-type: application/x-www-form-urlencoded;charset=UTF-8"] - expected: FAIL - - [Adding valid no-cors request header "content-type: multipart/form-data"] - expected: FAIL - - [Adding valid no-cors request header "content-type: multipart/form-data;charset=UTF-8"] - expected: FAIL - - [Adding valid no-cors request header "content-TYPE: text/plain"] - expected: FAIL - - [Adding valid no-cors request header "CONTENT-type: text/plain;charset=UTF-8"] - expected: FAIL - [Request should get its content-type from the body if none is provided] expected: FAIL