зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #16156 - Update http_network_or_cache_fetch according to spec (from ferjm:issue-16130-http-network-or-cache-fetch); r=jdm
There are still many steps blocked by the absence of an HTTP cache and the inability to trigger a credentials dialog. - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #16130 Source-Repo: https://github.com/servo/servo Source-Revision: 0f9dbcc8080e5763553d316261e2d158c19ce6f1 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 6ec4952d1393e06f98ca1f1cae413267c2d389c2
This commit is contained in:
Родитель
714c6b10e9
Коммит
02a67f151b
|
@ -747,15 +747,17 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
|
||||||
// TODO: Implement Window enum for Request
|
// TODO: Implement Window enum for Request
|
||||||
let request_has_no_window = true;
|
let request_has_no_window = true;
|
||||||
|
|
||||||
// Step 1
|
// Step 2
|
||||||
let http_request = if request_has_no_window &&
|
let http_request = if request_has_no_window &&
|
||||||
request.redirect_mode.get() == RedirectMode::Error {
|
request.redirect_mode.get() == RedirectMode::Error {
|
||||||
request
|
request
|
||||||
} else {
|
} else {
|
||||||
|
// Step 3
|
||||||
|
// TODO Implement body source
|
||||||
Rc::new((*request).clone())
|
Rc::new((*request).clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 2
|
// Step 4
|
||||||
let credentials_flag = match http_request.credentials_mode {
|
let credentials_flag = match http_request.credentials_mode {
|
||||||
CredentialsMode::Include => true,
|
CredentialsMode::Include => true,
|
||||||
CredentialsMode::CredentialsSameOrigin if http_request.response_tainting.get() == ResponseTainting::Basic
|
CredentialsMode::CredentialsSameOrigin if http_request.response_tainting.get() == ResponseTainting::Basic
|
||||||
|
@ -766,24 +768,24 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
|
||||||
let content_length_value = match *http_request.body.borrow() {
|
let content_length_value = match *http_request.body.borrow() {
|
||||||
None =>
|
None =>
|
||||||
match *http_request.method.borrow() {
|
match *http_request.method.borrow() {
|
||||||
// Step 4
|
// Step 6
|
||||||
Method::Post | Method::Put =>
|
Method::Post | Method::Put =>
|
||||||
Some(0),
|
Some(0),
|
||||||
// Step 3
|
// Step 5
|
||||||
_ => None
|
_ => None
|
||||||
},
|
},
|
||||||
// Step 5
|
// Step 7
|
||||||
Some(ref http_request_body) => Some(http_request_body.len() as u64)
|
Some(ref http_request_body) => Some(http_request_body.len() as u64)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 6
|
// Step 8
|
||||||
if let Some(content_length_value) = content_length_value {
|
if let Some(content_length_value) = content_length_value {
|
||||||
http_request.headers.borrow_mut().set(ContentLength(content_length_value));
|
http_request.headers.borrow_mut().set(ContentLength(content_length_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 7 TODO
|
// Step 9 TODO: needs request's client object
|
||||||
|
|
||||||
// Step 8
|
// Step 10
|
||||||
match *http_request.referrer.borrow() {
|
match *http_request.referrer.borrow() {
|
||||||
Referrer::NoReferrer => (),
|
Referrer::NoReferrer => (),
|
||||||
Referrer::ReferrerUrl(ref http_request_referrer) =>
|
Referrer::ReferrerUrl(ref http_request_referrer) =>
|
||||||
|
@ -794,7 +796,7 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 9
|
// Step 11
|
||||||
if !http_request.omit_origin_header.get() {
|
if !http_request.omit_origin_header.get() {
|
||||||
let method = http_request.method.borrow();
|
let method = http_request.method.borrow();
|
||||||
if cors_flag || (*method != Method::Get && *method != Method::Head) {
|
if cors_flag || (*method != Method::Get && *method != Method::Head) {
|
||||||
|
@ -807,24 +809,24 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 10
|
// Step 12
|
||||||
if !http_request.headers.borrow().has::<UserAgent>() {
|
if !http_request.headers.borrow().has::<UserAgent>() {
|
||||||
let user_agent = context.user_agent.clone().into_owned();
|
let user_agent = context.user_agent.clone().into_owned();
|
||||||
http_request.headers.borrow_mut().set(UserAgent(user_agent));
|
http_request.headers.borrow_mut().set(UserAgent(user_agent));
|
||||||
}
|
}
|
||||||
|
|
||||||
match http_request.cache_mode.get() {
|
match http_request.cache_mode.get() {
|
||||||
// Step 11
|
// Step 13
|
||||||
CacheMode::Default if is_no_store_cache(&http_request.headers.borrow()) => {
|
CacheMode::Default if is_no_store_cache(&http_request.headers.borrow()) => {
|
||||||
http_request.cache_mode.set(CacheMode::NoStore);
|
http_request.cache_mode.set(CacheMode::NoStore);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Step 12
|
// Step 14
|
||||||
CacheMode::NoCache if !http_request.headers.borrow().has::<CacheControl>() => {
|
CacheMode::NoCache if !http_request.headers.borrow().has::<CacheControl>() => {
|
||||||
http_request.headers.borrow_mut().set(CacheControl(vec![CacheDirective::MaxAge(0)]));
|
http_request.headers.borrow_mut().set(CacheControl(vec![CacheDirective::MaxAge(0)]));
|
||||||
},
|
},
|
||||||
|
|
||||||
// Step 13
|
// Step 15
|
||||||
CacheMode::Reload | CacheMode::NoStore => {
|
CacheMode::Reload | CacheMode::NoStore => {
|
||||||
// Substep 1
|
// Substep 1
|
||||||
if !http_request.headers.borrow().has::<Pragma>() {
|
if !http_request.headers.borrow().has::<Pragma>() {
|
||||||
|
@ -840,7 +842,7 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 14
|
// Step 16
|
||||||
let current_url = http_request.current_url();
|
let current_url = http_request.current_url();
|
||||||
{
|
{
|
||||||
let headers = &mut *http_request.headers.borrow_mut();
|
let headers = &mut *http_request.headers.borrow_mut();
|
||||||
|
@ -854,7 +856,7 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
|
||||||
set_default_accept_encoding(headers);
|
set_default_accept_encoding(headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 15
|
// Step 17
|
||||||
// TODO some of this step can't be implemented yet
|
// TODO some of this step can't be implemented yet
|
||||||
if credentials_flag {
|
if credentials_flag {
|
||||||
// Substep 1
|
// Substep 1
|
||||||
|
@ -892,96 +894,100 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 16
|
// Step 18
|
||||||
// TODO If there’s a proxy-authentication entry, use it as appropriate.
|
// TODO If there’s a proxy-authentication entry, use it as appropriate.
|
||||||
|
|
||||||
// Step 17
|
// Step 19
|
||||||
let mut response: Option<Response> = None;
|
let mut response: Option<Response> = None;
|
||||||
|
|
||||||
// Step 18
|
// Step 20
|
||||||
|
let mut revalidation_needed = false;
|
||||||
|
|
||||||
|
// Step 21
|
||||||
// TODO have a HTTP cache to check for a completed response
|
// TODO have a HTTP cache to check for a completed response
|
||||||
let complete_http_response_from_cache: Option<Response> = None;
|
let complete_http_response_from_cache: Option<Response> = None;
|
||||||
if http_request.cache_mode.get() != CacheMode::NoStore &&
|
if http_request.cache_mode.get() != CacheMode::NoStore &&
|
||||||
http_request.cache_mode.get() != CacheMode::Reload &&
|
http_request.cache_mode.get() != CacheMode::Reload &&
|
||||||
complete_http_response_from_cache.is_some() {
|
complete_http_response_from_cache.is_some() {
|
||||||
// Substep 1
|
// TODO Substep 1 and 2. Select a response from HTTP cache.
|
||||||
|
|
||||||
|
// Substep 3
|
||||||
|
if let Some(ref response) = response {
|
||||||
|
revalidation_needed = response_needs_revalidation(&response);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Substep 4
|
||||||
if http_request.cache_mode.get() == CacheMode::ForceCache ||
|
if http_request.cache_mode.get() == CacheMode::ForceCache ||
|
||||||
http_request.cache_mode.get() == CacheMode::OnlyIfCached {
|
http_request.cache_mode.get() == CacheMode::OnlyIfCached {
|
||||||
// TODO pull response from HTTP cache
|
// TODO pull response from HTTP cache
|
||||||
// response = http_request
|
// response = http_request
|
||||||
}
|
}
|
||||||
|
|
||||||
let revalidation_needed = match response {
|
if revalidation_needed {
|
||||||
Some(ref response) => response_needs_revalidation(&response),
|
// Substep 5
|
||||||
_ => false
|
// TODO set If-None-Match and If-Modified-Since according to cached
|
||||||
};
|
// response headers.
|
||||||
|
} else {
|
||||||
// Substep 2
|
// Substep 6
|
||||||
if !revalidation_needed && http_request.cache_mode.get() == CacheMode::Default {
|
|
||||||
// TODO pull response from HTTP cache
|
// TODO pull response from HTTP cache
|
||||||
// response = http_request
|
// response = http_request
|
||||||
// response.cache_state = CacheState::Local;
|
// response.cache_state = CacheState::Local;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Substep 3
|
|
||||||
if revalidation_needed && http_request.cache_mode.get() == CacheMode::Default ||
|
|
||||||
http_request.cache_mode.get() == CacheMode::NoCache {
|
|
||||||
// TODO this substep
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 19
|
// Step 22
|
||||||
// TODO have a HTTP cache to check for a partial response
|
|
||||||
} else if http_request.cache_mode.get() == CacheMode::Default ||
|
|
||||||
http_request.cache_mode.get() == CacheMode::ForceCache {
|
|
||||||
// TODO this substep
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 20
|
|
||||||
if response.is_none() {
|
if response.is_none() {
|
||||||
if http_request.cache_mode.get() == CacheMode::OnlyIfCached {
|
|
||||||
return Response::network_error(NetworkError::Internal("Couldn't find response in cache".into()))
|
|
||||||
}
|
|
||||||
response = Some(http_network_fetch(http_request.clone(), credentials_flag,
|
|
||||||
done_chan, context));
|
|
||||||
}
|
|
||||||
let response = response.unwrap();
|
|
||||||
|
|
||||||
if let Some(status) = response.status {
|
|
||||||
match status {
|
|
||||||
StatusCode::NotModified => {
|
|
||||||
// Step 21
|
|
||||||
if http_request.cache_mode.get() == CacheMode::Default ||
|
|
||||||
http_request.cache_mode.get() == CacheMode::NoCache {
|
|
||||||
// Substep 1
|
// Substep 1
|
||||||
// TODO this substep
|
if http_request.cache_mode.get() == CacheMode::OnlyIfCached {
|
||||||
// let cached_response: Option<Response> = None;
|
return Response::network_error(
|
||||||
|
NetworkError::Internal("Couldn't find response in cache".into()))
|
||||||
|
}
|
||||||
// Substep 2
|
// Substep 2
|
||||||
// if cached_response.is_none() {
|
let forward_response = http_network_fetch(http_request.clone(), credentials_flag,
|
||||||
// return Response::network_error();
|
done_chan, context);
|
||||||
// }
|
match forward_response.raw_status {
|
||||||
|
|
||||||
// Substep 3
|
// Substep 3
|
||||||
|
Some((200...303, _)) |
|
||||||
// Substep 4
|
Some((305...399, _)) => {
|
||||||
// response = cached_response;
|
if !http_request.method.borrow().safe() {
|
||||||
|
// TODO Invalidate HTTP cache response
|
||||||
// Substep 5
|
|
||||||
// TODO cache_state is immutable?
|
|
||||||
// response.cache_state = CacheState::Validated;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
StatusCode::Unauthorized => {
|
// Substep 4
|
||||||
// Step 22
|
Some((304, _)) => {
|
||||||
|
if revalidation_needed {
|
||||||
|
// TODO update forward_response headers with cached response
|
||||||
|
// headers
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Substep 5
|
||||||
|
if response.is_none() {
|
||||||
|
response = Some(forward_response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let response = response.unwrap();
|
||||||
|
|
||||||
|
match response.status {
|
||||||
|
Some(StatusCode::Unauthorized) => {
|
||||||
|
// Step 23
|
||||||
// FIXME: Figure out what to do with request window objects
|
// FIXME: Figure out what to do with request window objects
|
||||||
if cors_flag && !credentials_flag {
|
if cors_flag && !credentials_flag {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 1
|
// Substep 1
|
||||||
// TODO: Spec says requires testing on multiple WWW-Authenticate headers
|
// TODO: Spec says requires testing on multiple WWW-Authenticate headers
|
||||||
|
|
||||||
// Step 2
|
// Substep 2
|
||||||
|
if http_request.body.borrow().is_some() {
|
||||||
|
// TODO Implement body source
|
||||||
|
}
|
||||||
|
|
||||||
|
// Substep 3
|
||||||
if !http_request.use_url_credentials || authentication_fetch_flag {
|
if !http_request.use_url_credentials || authentication_fetch_flag {
|
||||||
// TODO: Prompt the user for username and password from the window
|
// TODO: Prompt the user for username and password from the window
|
||||||
// Wrong, but will have to do until we are able to prompt the user
|
// Wrong, but will have to do until we are able to prompt the user
|
||||||
|
@ -990,11 +996,13 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3
|
// Substep 4
|
||||||
return http_network_or_cache_fetch(http_request, true, cors_flag, done_chan, context);
|
return http_network_or_cache_fetch(http_request,
|
||||||
|
true /* authentication flag */,
|
||||||
|
cors_flag, done_chan, context);
|
||||||
},
|
},
|
||||||
StatusCode::ProxyAuthenticationRequired => {
|
Some(StatusCode::ProxyAuthenticationRequired) => {
|
||||||
// Step 23
|
// Step 24
|
||||||
// Step 1
|
// Step 1
|
||||||
// TODO: Figure out what to do with request window objects
|
// TODO: Figure out what to do with request window objects
|
||||||
|
|
||||||
|
@ -1014,14 +1022,13 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Step 24
|
// Step 25
|
||||||
if authentication_fetch_flag {
|
if authentication_fetch_flag {
|
||||||
// TODO Create the authentication entry for request and the given realm
|
// TODO Create the authentication entry for request and the given realm
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 25
|
// Step 26
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче