mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Append the Sec-Purpose header for prefetch requests (#33490)
Signed-off-by: Shane Handley <shanehandley@fastmail.com>
This commit is contained in:
parent
aa5bf94b35
commit
777a3ec13f
1 changed files with 51 additions and 23 deletions
|
@ -41,6 +41,7 @@ use net_traits::request::{
|
||||||
is_cors_safelisted_method, is_cors_safelisted_request_header, BodyChunkRequest,
|
is_cors_safelisted_method, is_cors_safelisted_request_header, BodyChunkRequest,
|
||||||
BodyChunkResponse, CacheMode, CredentialsMode, Destination, Initiator, Origin, RedirectMode,
|
BodyChunkResponse, CacheMode, CredentialsMode, Destination, Initiator, Origin, RedirectMode,
|
||||||
Referrer, Request, RequestBuilder, RequestMode, ResponseTainting, ServiceWorkersMode,
|
Referrer, Request, RequestBuilder, RequestMode, ResponseTainting, ServiceWorkersMode,
|
||||||
|
Window as RequestWindow,
|
||||||
};
|
};
|
||||||
use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType};
|
use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType};
|
||||||
use net_traits::{
|
use net_traits::{
|
||||||
|
@ -1095,27 +1096,33 @@ async fn http_network_or_cache_fetch(
|
||||||
done_chan: &mut DoneChannel,
|
done_chan: &mut DoneChannel,
|
||||||
context: &FetchContext,
|
context: &FetchContext,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
// Step 2
|
// Step 3: Let httpRequest be null.
|
||||||
|
let mut http_request;
|
||||||
|
|
||||||
|
// Step 4: Let response be null.
|
||||||
let mut response: Option<Response> = None;
|
let mut response: Option<Response> = None;
|
||||||
// Step 4
|
|
||||||
|
// Step 7: Let the revalidatingFlag be unset.
|
||||||
let mut revalidating_flag = false;
|
let mut revalidating_flag = false;
|
||||||
|
|
||||||
// TODO: Implement Window enum for Request
|
// Step 8.1: If request’s window is "no-window" and request’s redirect mode is "error", then set
|
||||||
let request_has_no_window = true;
|
// httpFetchParams to fetchParams and httpRequest to request.
|
||||||
|
let request_has_no_window = request.window == RequestWindow::NoWindow;
|
||||||
|
|
||||||
// Step 5.1
|
|
||||||
let mut http_request;
|
|
||||||
let http_request = if request_has_no_window && request.redirect_mode == RedirectMode::Error {
|
let http_request = if request_has_no_window && request.redirect_mode == RedirectMode::Error {
|
||||||
request
|
request
|
||||||
} else {
|
} else {
|
||||||
// Step 5.2.1, .2.2 and .2.3 and 2.4
|
// Step 8.2.1: Set httpRequest to a clone of request.
|
||||||
http_request = request.clone();
|
http_request = request.clone();
|
||||||
|
|
||||||
&mut http_request
|
&mut http_request
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 5.3
|
// Step 8.3: Let includeCredentials be true if one of:
|
||||||
let credentials_flag = match http_request.credentials_mode {
|
let include_credentials = match http_request.credentials_mode {
|
||||||
|
// request’s credentials mode is "include"
|
||||||
CredentialsMode::Include => true,
|
CredentialsMode::Include => true,
|
||||||
|
// request’s credentials mode is "same-origin" and request’s response tainting is "basic"
|
||||||
CredentialsMode::CredentialsSameOrigin
|
CredentialsMode::CredentialsSameOrigin
|
||||||
if http_request.response_tainting == ResponseTainting::Basic =>
|
if http_request.response_tainting == ResponseTainting::Basic =>
|
||||||
{
|
{
|
||||||
|
@ -1124,33 +1131,42 @@ async fn http_network_or_cache_fetch(
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Step 8.4: If Cross-Origin-Embedder-Policy allows credentials with request returns false, then
|
||||||
|
// set includeCredentials to false.
|
||||||
|
// TODO: Requires request's client object
|
||||||
|
|
||||||
|
// Step 8.5: Let contentLength be httpRequest’s body’s length, if httpRequest’s body is
|
||||||
|
// non-null; otherwise null.
|
||||||
let content_length_value = match http_request.body {
|
let content_length_value = match http_request.body {
|
||||||
|
Some(ref http_request_body) => http_request_body.len().map(|size| size as u64),
|
||||||
|
// Step 8.7: If httpRequest’s body is null and httpRequest’s method is `POST` or `PUT`, then
|
||||||
|
// set contentLengthHeaderValue to `0`.
|
||||||
None => match http_request.method {
|
None => match http_request.method {
|
||||||
// Step 5.5
|
|
||||||
Method::POST | Method::PUT => Some(0),
|
Method::POST | Method::PUT => Some(0),
|
||||||
// Step 5.4
|
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
// Step 5.6
|
|
||||||
Some(ref http_request_body) => http_request_body.len().map(|size| size as u64),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 5.7
|
// Step 8.9: If contentLengthHeaderValue is non-null, then append (`Content-Length`,
|
||||||
|
// contentLengthHeaderValue) to httpRequest’s header list.
|
||||||
if let Some(content_length_value) = content_length_value {
|
if let Some(content_length_value) = content_length_value {
|
||||||
http_request
|
http_request
|
||||||
.headers
|
.headers
|
||||||
.typed_insert(ContentLength(content_length_value));
|
.typed_insert(ContentLength(content_length_value));
|
||||||
if http_request.keep_alive {
|
|
||||||
// Step 5.8 TODO: needs request's client object
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 5.9
|
// Step 8.10: If contentLength is non-null and httpRequest’s keepalive is true, then:
|
||||||
|
// TODO Keepalive requires request's client object's fetch group
|
||||||
|
|
||||||
|
// Step 8.11: If httpRequest’s referrer is a URL, then:
|
||||||
match http_request.referrer {
|
match http_request.referrer {
|
||||||
Referrer::NoReferrer => (),
|
Referrer::NoReferrer => (),
|
||||||
Referrer::ReferrerUrl(ref http_request_referrer) |
|
Referrer::ReferrerUrl(ref http_request_referrer) |
|
||||||
Referrer::Client(ref http_request_referrer) => {
|
Referrer::Client(ref http_request_referrer) => {
|
||||||
|
// Step 8.11.1: Let referrerValue be httpRequest’s referrer, serialized and isomorphic
|
||||||
|
// encoded.
|
||||||
if let Ok(referer) = http_request_referrer.to_string().parse::<Referer>() {
|
if let Ok(referer) = http_request_referrer.to_string().parse::<Referer>() {
|
||||||
|
// Step 8.11.2: Append (`Referer`, referrerValue) to httpRequest’s header list.
|
||||||
http_request.headers.typed_insert(referer);
|
http_request.headers.typed_insert(referer);
|
||||||
} else {
|
} else {
|
||||||
// This error should only happen in cases where hyper and rust-url disagree
|
// This error should only happen in cases where hyper and rust-url disagree
|
||||||
|
@ -1161,7 +1177,7 @@ async fn http_network_or_cache_fetch(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 5.10
|
// Step 8.12: Append a request `Origin` header for httpRequest.
|
||||||
if cors_flag || (http_request.method != Method::GET && http_request.method != Method::HEAD) {
|
if cors_flag || (http_request.method != Method::GET && http_request.method != Method::HEAD) {
|
||||||
debug_assert_ne!(http_request.origin, Origin::Client);
|
debug_assert_ne!(http_request.origin, Origin::Client);
|
||||||
if let Origin::Origin(ref url_origin) = http_request.origin {
|
if let Origin::Origin(ref url_origin) = http_request.origin {
|
||||||
|
@ -1171,7 +1187,19 @@ async fn http_network_or_cache_fetch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 5.11
|
// Step 8.13: Append the Fetch metadata headers for httpRequest.
|
||||||
|
// TODO Implement Sec-Fetch-* headers
|
||||||
|
|
||||||
|
// Step 8.14: If httpRequest’s initiator is "prefetch", then set a structured field value given
|
||||||
|
// (`Sec-Purpose`, the token "prefetch") in httpRequest’s header list.
|
||||||
|
if http_request.initiator == Initiator::Prefetch {
|
||||||
|
if let Ok(value) = HeaderValue::from_str("prefetch") {
|
||||||
|
http_request.headers.insert("Sec-Purpose", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 8.15: If httpRequest’s header list does not contain `User-Agent`, then user agents
|
||||||
|
// should append (`User-Agent`, default `User-Agent` value) to httpRequest’s header list.
|
||||||
if !http_request.headers.contains_key(header::USER_AGENT) {
|
if !http_request.headers.contains_key(header::USER_AGENT) {
|
||||||
let user_agent = context.user_agent.clone().into_owned();
|
let user_agent = context.user_agent.clone().into_owned();
|
||||||
http_request
|
http_request
|
||||||
|
@ -1223,7 +1251,7 @@ async fn http_network_or_cache_fetch(
|
||||||
|
|
||||||
// Step 5.17
|
// Step 5.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 include_credentials {
|
||||||
// Substep 1
|
// Substep 1
|
||||||
// TODO http://mxr.mozilla.org/servo/source/components/net/http_loader.rs#504
|
// TODO http://mxr.mozilla.org/servo/source/components/net/http_loader.rs#504
|
||||||
// XXXManishearth http_loader has block_cookies: support content blocking here too
|
// XXXManishearth http_loader has block_cookies: support content blocking here too
|
||||||
|
@ -1436,7 +1464,7 @@ async fn http_network_or_cache_fetch(
|
||||||
if response.is_none() {
|
if response.is_none() {
|
||||||
// Substep 2
|
// Substep 2
|
||||||
let forward_response =
|
let forward_response =
|
||||||
http_network_fetch(http_request, credentials_flag, done_chan, context).await;
|
http_network_fetch(http_request, include_credentials, done_chan, context).await;
|
||||||
// Substep 3
|
// Substep 3
|
||||||
if let Some((200..=399, _)) = forward_response.raw_status {
|
if let Some((200..=399, _)) = forward_response.raw_status {
|
||||||
if !http_request.method.is_safe() {
|
if !http_request.method.is_safe() {
|
||||||
|
@ -1555,7 +1583,7 @@ async fn http_network_or_cache_fetch(
|
||||||
// Step 10
|
// Step 10
|
||||||
// FIXME: Figure out what to do with request window objects
|
// FIXME: Figure out what to do with request window objects
|
||||||
if let (Some((StatusCode::UNAUTHORIZED, _)), false, true) =
|
if let (Some((StatusCode::UNAUTHORIZED, _)), false, true) =
|
||||||
(response.status.as_ref(), cors_flag, credentials_flag)
|
(response.status.as_ref(), cors_flag, include_credentials)
|
||||||
{
|
{
|
||||||
// Substep 1
|
// Substep 1
|
||||||
// TODO: Spec says requires testing on multiple WWW-Authenticate headers
|
// TODO: Spec says requires testing on multiple WWW-Authenticate headers
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue