New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update fetch methods #17521
Merged
+255
−257
Merged
Update fetch methods #17521
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
ed9c165
Update main fetch
KiChjang b50bcdc
Rename basic fetch to scheme fetch
KiChjang 0ff47c4
Update HTTP fetch
KiChjang d6c197b
Update HTTP-redirect fetch
KiChjang 5b69d18
Add location_url to Metadata struct
KiChjang 99f5935
Update HTTP-network-or-cache fetch
KiChjang 34178bd
Update HTTP-network fetch
KiChjang 4a4caa8
Update CORS preflight fetch
KiChjang f28a6a0
Fix unit tests for updated CORS preflight fetch
KiChjang 268f78e
Update test expectations
KiChjang File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.
| @@ -10,14 +10,14 @@ use filemanager_thread::FileManager; | ||
| use http_loader::{HttpState, determine_request_referrer, http_fetch}; | ||
| use http_loader::{set_default_accept, set_default_accept_language}; | ||
| use hyper::{Error, Result as HyperResult}; | ||
| use hyper::header::{Accept, AcceptLanguage, ContentLanguage, ContentType}; | ||
| use hyper::header::{Accept, AcceptLanguage, AccessControlExposeHeaders, ContentLanguage, ContentType}; | ||
| use hyper::header::{Header, HeaderFormat, HeaderView, Headers, Referer as RefererHeader}; | ||
| use hyper::method::Method; | ||
| use hyper::mime::{Mime, SubLevel, TopLevel}; | ||
| use hyper::status::StatusCode; | ||
| use mime_guess::guess_mime_type; | ||
| use net_traits::{FetchTaskTarget, NetworkError, ReferrerPolicy}; | ||
| use net_traits::request::{Referrer, Request, RequestMode, ResponseTainting}; | ||
| use net_traits::request::{CredentialsMode, Referrer, Request, RequestMode, ResponseTainting}; | ||
| use net_traits::request::{Type, Origin, Window}; | ||
| use net_traits::response::{Response, ResponseBody, ResponseType}; | ||
| use servo_url::ServoUrl; | ||
| @@ -107,9 +107,8 @@ pub fn main_fetch(request: &mut Request, | ||
|
|
||
| // Step 2. | ||
| if request.local_urls_only { | ||
| match request.current_url().scheme() { | ||
| "about" | "blob" | "data" | "filesystem" => (), // Ok, the URL is local. | ||
| _ => response = Some(Response::network_error(NetworkError::Internal("Non-local scheme".into()))) | ||
| if !matches!(request.current_url().scheme(), "about" | "blob" | "data" | "filesystem") { | ||
| response = Some(Response::network_error(NetworkError::Internal("Non-local scheme".into()))); | ||
| } | ||
| } | ||
|
|
||
| @@ -130,8 +129,7 @@ pub fn main_fetch(request: &mut Request, | ||
| // TODO: handle request's client's referrer policy. | ||
|
|
||
| // Step 7. | ||
| let referrer_policy = request.referrer_policy.unwrap_or(ReferrerPolicy::NoReferrerWhenDowngrade); | ||
| request.referrer_policy = Some(referrer_policy); | ||
| request.referrer_policy = request.referrer_policy.or(Some(ReferrerPolicy::NoReferrerWhenDowngrade)); | ||
|
|
||
| // Step 8. | ||
| { | ||
| @@ -147,7 +145,7 @@ pub fn main_fetch(request: &mut Request, | ||
| request.headers.remove::<RefererHeader>(); | ||
| let current_url = request.current_url().clone(); | ||
| determine_request_referrer(&mut request.headers, | ||
| referrer_policy, | ||
| request.referrer_policy.unwrap(), | ||
| url, | ||
| current_url) | ||
| } | ||
| @@ -168,7 +166,7 @@ pub fn main_fetch(request: &mut Request, | ||
| // Not applicable: see fetch_async. | ||
|
|
||
| // Step 12. | ||
| let response = response.unwrap_or_else(|| { | ||
| let mut response = response.unwrap_or_else(|| { | ||
| let current_url = request.current_url(); | ||
| let same_origin = if let Origin::Origin(ref origin) = request.origin { | ||
| *origin == current_url.origin() | ||
| @@ -178,35 +176,50 @@ pub fn main_fetch(request: &mut Request, | ||
|
|
||
| if (same_origin && !cors_flag ) || | ||
| current_url.scheme() == "data" || | ||
| current_url.scheme() == "file" || | ||
KiChjang
Author
Member
|
||
| current_url.scheme() == "file" || // FIXME: Fetch spec has already dropped filtering against file: | ||
| // and about: schemes, but CSS tests will break on loading Ahem | ||
| // since we load them through a file: URL. | ||
| current_url.scheme() == "about" || | ||
| request.mode == RequestMode::Navigate { | ||
| basic_fetch(request, cache, target, done_chan, context) | ||
| // Substep 1. | ||
| request.response_tainting = ResponseTainting::Basic; | ||
|
|
||
| // Substep 2. | ||
| scheme_fetch(request, cache, target, done_chan, context) | ||
|
|
||
| } else if request.mode == RequestMode::SameOrigin { | ||
| Response::network_error(NetworkError::Internal("Cross-origin response".into())) | ||
|
|
||
| } else if request.mode == RequestMode::NoCors { | ||
| // Substep 1. | ||
| request.response_tainting = ResponseTainting::Opaque; | ||
| basic_fetch(request, cache, target, done_chan, context) | ||
|
|
||
| // Substep 2. | ||
| scheme_fetch(request, cache, target, done_chan, context) | ||
|
|
||
| } else if !matches!(current_url.scheme(), "http" | "https") { | ||
| Response::network_error(NetworkError::Internal("Non-http scheme".into())) | ||
|
|
||
| } else if request.use_cors_preflight || | ||
| (request.unsafe_request && | ||
| (!is_simple_method(&request.method) || | ||
| request.headers.iter().any(|h| !is_simple_header(&h)))) { | ||
| (!is_cors_safelisted_method(&request.method) || | ||
| request.headers.iter().any(|h| !is_cors_safelisted_request_header(&h)))) { | ||
| // Substep 1. | ||
| request.response_tainting = ResponseTainting::CorsTainting; | ||
| // Substep 2. | ||
| let response = http_fetch(request, cache, true, true, false, | ||
| target, done_chan, context); | ||
| // Substep 3. | ||
| if response.is_network_error() { | ||
| // TODO clear cache entries using request | ||
| } | ||
| // Substep 4. | ||
| response | ||
|
|
||
| } else { | ||
| // Substep 1. | ||
| request.response_tainting = ResponseTainting::CorsTainting; | ||
| // Substep 2. | ||
| http_fetch(request, cache, true, false, false, target, done_chan, context) | ||
| } | ||
| }); | ||
| @@ -217,9 +230,28 @@ pub fn main_fetch(request: &mut Request, | ||
| } | ||
|
|
||
| // Step 14. | ||
| // We don't need to check whether response is a network error, | ||
| // given its type would not be `Default` in this case. | ||
| let mut response = if response.response_type == ResponseType::Default { | ||
| let mut response = if !response.is_network_error() && response.internal_response.is_none() { | ||
| // Substep 1. | ||
| if request.response_tainting == ResponseTainting::CorsTainting { | ||
| // Subsubstep 1. | ||
| let header_names = response.headers.get::<AccessControlExposeHeaders>(); | ||
| match header_names { | ||
| // Subsubstep 2. | ||
| Some(list) if request.credentials_mode != CredentialsMode::Include => { | ||
| if list.len() == 1 && list[0] == "*" { | ||
| response.cors_exposed_header_name_list = | ||
| response.headers.iter().map(|h| h.name().to_owned()).collect(); | ||
| } | ||
| }, | ||
| // Subsubstep 3. | ||
| Some(list) => { | ||
| response.cors_exposed_header_name_list = list.iter().map(|h| (**h).clone()).collect(); | ||
| }, | ||
| _ => (), | ||
| } | ||
| } | ||
|
|
||
| // Substep 2. | ||
| let response_type = match request.response_tainting { | ||
| ResponseTainting::Basic => ResponseType::Basic, | ||
| ResponseTainting::CorsTainting => ResponseType::Cors, | ||
| @@ -365,7 +397,7 @@ fn wait_for_response(response: &Response, target: Target, done_chan: &mut DoneCh | ||
| let body = response.body.lock().unwrap(); | ||
| if let ResponseBody::Done(ref vec) = *body { | ||
| // in case there was no channel to wait for, the body was | ||
| // obtained synchronously via basic_fetch for data/file/about/etc | ||
| // obtained synchronously via scheme_fetch for data/file/about/etc | ||
| // We should still send the body across as a chunk | ||
| target.process_response_chunk(vec.clone()); | ||
| } else { | ||
| @@ -374,8 +406,8 @@ fn wait_for_response(response: &Response, target: Target, done_chan: &mut DoneCh | ||
| } | ||
| } | ||
|
|
||
| /// [Basic fetch](https://fetch.spec.whatwg.org#basic-fetch) | ||
| fn basic_fetch(request: &mut Request, | ||
| /// [Scheme fetch](https://fetch.spec.whatwg.org#scheme-fetch) | ||
| fn scheme_fetch(request: &mut Request, | ||
| cache: &mut CorsCache, | ||
| target: Target, | ||
| done_chan: &mut DoneChannel, | ||
| @@ -463,7 +495,7 @@ fn basic_fetch(request: &mut Request, | ||
| } | ||
|
|
||
| /// https://fetch.spec.whatwg.org/#cors-safelisted-request-header | ||
| pub fn is_simple_header(h: &HeaderView) -> bool { | ||
| pub fn is_cors_safelisted_request_header(h: &HeaderView) -> bool { | ||
| if h.is::<ContentType>() { | ||
| match h.value() { | ||
| Some(&ContentType(Mime(TopLevel::Text, SubLevel::Plain, _))) | | ||
| @@ -477,7 +509,8 @@ pub fn is_simple_header(h: &HeaderView) -> bool { | ||
| } | ||
| } | ||
|
|
||
| pub fn is_simple_method(m: &Method) -> bool { | ||
| /// https://fetch.spec.whatwg.org/#cors-safelisted-method | ||
| pub fn is_cors_safelisted_method(m: &Method) -> bool { | ||
| match *m { | ||
| Method::Get | Method::Head | Method::Post => true, | ||
| _ => false | ||
Oops, something went wrong.
ProTip!
Use n and p to navigate between commits in a pull request.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
I am 99% sure this is going to hit the same problem as #14515 (comment) .