mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Refactor http_fetch to reflect the new standard
This commit is contained in:
parent
7623e89506
commit
7d3eb72a26
3 changed files with 152 additions and 83 deletions
|
@ -11,10 +11,13 @@ use hyper::header::{QualityItem, q, qitem};
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value};
|
use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value};
|
||||||
use hyper::status::StatusCode;
|
use hyper::status::StatusCode;
|
||||||
use net_traits::{AsyncFetchListener, Response, ResponseType, Metadata};
|
use net_traits::{AsyncFetchListener, Response};
|
||||||
|
use net_traits::{ResponseType, Metadata};
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use url::Url;
|
use url::{Url, UrlParser};
|
||||||
use util::task::spawn_named;
|
use util::task::spawn_named;
|
||||||
|
|
||||||
/// A [request context](https://fetch.spec.whatwg.org/#concept-request-context)
|
/// A [request context](https://fetch.spec.whatwg.org/#concept-request-context)
|
||||||
|
@ -90,7 +93,8 @@ pub enum ResponseTainting {
|
||||||
/// A [Request](https://fetch.spec.whatwg.org/#requests) as defined by the Fetch spec
|
/// A [Request](https://fetch.spec.whatwg.org/#requests) as defined by the Fetch spec
|
||||||
pub struct Request {
|
pub struct Request {
|
||||||
pub method: Method,
|
pub method: Method,
|
||||||
pub url: Url,
|
// Use the last method on url_list to act as spec url field
|
||||||
|
pub url_list: Vec<Url>,
|
||||||
pub headers: Headers,
|
pub headers: Headers,
|
||||||
pub unsafe_request: bool,
|
pub unsafe_request: bool,
|
||||||
pub body: Option<Vec<u8>>,
|
pub body: Option<Vec<u8>>,
|
||||||
|
@ -101,7 +105,7 @@ pub struct Request {
|
||||||
pub skip_service_worker: bool,
|
pub skip_service_worker: bool,
|
||||||
pub context: Context,
|
pub context: Context,
|
||||||
pub context_frame_type: ContextFrameType,
|
pub context_frame_type: ContextFrameType,
|
||||||
pub origin: Option<Url>,
|
pub origin: Option<Url>, // FIXME: Use Url::Origin
|
||||||
pub force_origin_header: bool,
|
pub force_origin_header: bool,
|
||||||
pub same_origin_data: bool,
|
pub same_origin_data: bool,
|
||||||
pub referer: Referer,
|
pub referer: Referer,
|
||||||
|
@ -121,7 +125,7 @@ impl Request {
|
||||||
pub fn new(url: Url, context: Context, is_service_worker_global_scope: bool) -> Request {
|
pub fn new(url: Url, context: Context, is_service_worker_global_scope: bool) -> Request {
|
||||||
Request {
|
Request {
|
||||||
method: Method::Get,
|
method: Method::Get,
|
||||||
url: url,
|
url_list: vec![url],
|
||||||
headers: Headers::new(),
|
headers: Headers::new(),
|
||||||
unsafe_request: false,
|
unsafe_request: false,
|
||||||
body: None,
|
body: None,
|
||||||
|
@ -147,13 +151,17 @@ impl Request {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_last_url_string(&self) -> String {
|
||||||
|
self.url_list.last().unwrap().serialize()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fetch_async(mut self,
|
pub fn fetch_async(mut self,
|
||||||
cors_flag: bool,
|
cors_flag: bool,
|
||||||
listener: Box<AsyncFetchListener + Send>) {
|
listener: Box<AsyncFetchListener + Send>) {
|
||||||
spawn_named(format!("fetch for {:?}", self.url.serialize()), move || {
|
spawn_named(format!("fetch for {:?}", self.get_last_url_string()), move || {
|
||||||
let res = self.fetch(cors_flag);
|
let res = self.fetch(cors_flag);
|
||||||
listener.response_available(res);
|
listener.response_available(res);
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [Fetch](https://fetch.spec.whatwg.org#concept-fetch)
|
/// [Fetch](https://fetch.spec.whatwg.org#concept-fetch)
|
||||||
|
@ -211,8 +219,11 @@ impl Request {
|
||||||
|
|
||||||
/// [Basic fetch](https://fetch.spec.whatwg.org#basic-fetch)
|
/// [Basic fetch](https://fetch.spec.whatwg.org#basic-fetch)
|
||||||
pub fn basic_fetch(&mut self) -> Response {
|
pub fn basic_fetch(&mut self) -> Response {
|
||||||
match &*self.url.scheme {
|
let scheme = self.url_list.last().unwrap().scheme.clone();
|
||||||
"about" => match self.url.non_relative_scheme_data() {
|
match &*scheme {
|
||||||
|
"about" => {
|
||||||
|
let url = self.url_list.last().unwrap();
|
||||||
|
match url.non_relative_scheme_data() {
|
||||||
Some(s) if &*s == "blank" => {
|
Some(s) if &*s == "blank" => {
|
||||||
let mut response = Response::new();
|
let mut response = Response::new();
|
||||||
response.headers.set(ContentType(Mime(
|
response.headers.set(ContentType(Mime(
|
||||||
|
@ -221,7 +232,8 @@ impl Request {
|
||||||
response
|
response
|
||||||
},
|
},
|
||||||
_ => Response::network_error()
|
_ => Response::network_error()
|
||||||
},
|
}
|
||||||
|
}
|
||||||
"http" | "https" => {
|
"http" | "https" => {
|
||||||
self.http_fetch(false, false, false)
|
self.http_fetch(false, false, false)
|
||||||
},
|
},
|
||||||
|
@ -234,31 +246,64 @@ impl Request {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn http_fetch_async(mut self, cors_flag: bool,
|
||||||
|
cors_preflight_flag: bool,
|
||||||
|
authentication_fetch_flag: bool,
|
||||||
|
listener: Box<AsyncFetchListener + Send>) {
|
||||||
|
spawn_named(format!("http_fetch for {:?}", self.get_last_url_string()), move || {
|
||||||
|
let res = self.http_fetch(cors_flag, cors_preflight_flag,
|
||||||
|
authentication_fetch_flag);
|
||||||
|
listener.response_available(res);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// [HTTP fetch](https://fetch.spec.whatwg.org#http-fetch)
|
/// [HTTP fetch](https://fetch.spec.whatwg.org#http-fetch)
|
||||||
pub fn http_fetch(&mut self, cors_flag: bool, cors_preflight_flag: bool,
|
pub fn http_fetch(&mut self, cors_flag: bool, cors_preflight_flag: bool,
|
||||||
authentication_fetch_flag: bool) -> Response {
|
authentication_fetch_flag: bool) -> Response {
|
||||||
// Step 1
|
// Step 1
|
||||||
let mut response: Option<Response> = None;
|
let mut response: Option<Rc<RefCell<Response>>> = None;
|
||||||
// Step 2
|
// Step 2
|
||||||
|
let mut actual_response: Option<Rc<RefCell<Response>>> = None;
|
||||||
|
// Step 3
|
||||||
if !self.skip_service_worker && !self.is_service_worker_global_scope {
|
if !self.skip_service_worker && !self.is_service_worker_global_scope {
|
||||||
// TODO: Substep 1 (handle fetch unimplemented)
|
// TODO: Substep 1 (handle fetch unimplemented)
|
||||||
// Substep 2
|
|
||||||
if let Some(ref res) = response {
|
if let Some(ref res) = response {
|
||||||
if (res.response_type == ResponseType::Opaque && self.mode != RequestMode::NoCORS) ||
|
let resp = res.borrow();
|
||||||
res.response_type == ResponseType::Error {
|
// Substep 2
|
||||||
|
actual_response = match resp.internal_response {
|
||||||
|
Some(ref internal_res) => Some(internal_res.clone()),
|
||||||
|
None => Some(res.clone())
|
||||||
|
};
|
||||||
|
// Substep 3
|
||||||
|
if (resp.response_type == ResponseType::Opaque &&
|
||||||
|
self.mode != RequestMode::NoCORS) ||
|
||||||
|
(resp.response_type == ResponseType::OpaqueRedirect &&
|
||||||
|
self.redirect_mode != RedirectMode::Manual) ||
|
||||||
|
resp.response_type == ResponseType::Error {
|
||||||
return Response::network_error();
|
return Response::network_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Substep 4
|
||||||
|
if let Some(ref res) = actual_response {
|
||||||
|
let mut resp = res.borrow_mut();
|
||||||
|
if resp.url_list.is_empty() {
|
||||||
|
resp.url_list = self.url_list.clone();
|
||||||
}
|
}
|
||||||
// Step 3
|
}
|
||||||
|
// Substep 5
|
||||||
|
// TODO: set response's CSP list on actual_response
|
||||||
|
}
|
||||||
|
// Step 4
|
||||||
if response.is_none() {
|
if response.is_none() {
|
||||||
// Substep 1
|
// Substep 1
|
||||||
if cors_preflight_flag {
|
if cors_preflight_flag {
|
||||||
let mut method_mismatch = false;
|
let mut method_mismatch = false;
|
||||||
let mut header_mismatch = false;
|
let mut header_mismatch = false;
|
||||||
if let Some(ref mut cache) = self.cache {
|
if let Some(ref mut cache) = self.cache {
|
||||||
|
// FIXME: Once Url::Origin is available, rewrite origin to
|
||||||
|
// take an Origin instead of a Url
|
||||||
let origin = self.origin.clone().unwrap_or(Url::parse("").unwrap());
|
let origin = self.origin.clone().unwrap_or(Url::parse("").unwrap());
|
||||||
let url = self.url.clone();
|
let url = self.url_list.last().unwrap().clone();
|
||||||
let credentials = self.credentials_mode == CredentialsMode::Include;
|
let credentials = self.credentials_mode == CredentialsMode::Include;
|
||||||
let method_cache_match = cache.match_method(CacheRequestDetails {
|
let method_cache_match = cache.match_method(CacheRequestDetails {
|
||||||
origin: origin.clone(),
|
origin: origin.clone(),
|
||||||
|
@ -280,7 +325,7 @@ impl Request {
|
||||||
if preflight_result.response_type == ResponseType::Error {
|
if preflight_result.response_type == ResponseType::Error {
|
||||||
return Response::network_error();
|
return Response::network_error();
|
||||||
}
|
}
|
||||||
response = Some(preflight_result);
|
response = Some(Rc::new(RefCell::new(preflight_result)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Substep 2
|
// Substep 2
|
||||||
|
@ -288,31 +333,24 @@ impl Request {
|
||||||
// Substep 3
|
// Substep 3
|
||||||
let credentials = match self.credentials_mode {
|
let credentials = match self.credentials_mode {
|
||||||
CredentialsMode::Include => true,
|
CredentialsMode::Include => true,
|
||||||
CredentialsMode::CredentialsSameOrigin if !cors_flag => true,
|
CredentialsMode::CredentialsSameOrigin if (!cors_flag ||
|
||||||
|
self.response_tainting == ResponseTainting::Opaque)
|
||||||
|
=> true,
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
// Substep 4
|
// Substep 4
|
||||||
if self.cache_mode == CacheMode::Default && is_no_store_cache(&self.headers) {
|
|
||||||
self.cache_mode = CacheMode::NoStore;
|
|
||||||
}
|
|
||||||
// Substep 5
|
|
||||||
let fetch_result = self.http_network_or_cache_fetch(credentials, authentication_fetch_flag);
|
let fetch_result = self.http_network_or_cache_fetch(credentials, authentication_fetch_flag);
|
||||||
// Substep 6
|
// Substep 5
|
||||||
if cors_flag && self.cors_check(&fetch_result).is_err() {
|
if cors_flag && self.cors_check(&fetch_result).is_err() {
|
||||||
return Response::network_error();
|
return Response::network_error();
|
||||||
}
|
}
|
||||||
response = Some(fetch_result);
|
response = Some(Rc::new(RefCell::new(fetch_result)));
|
||||||
|
actual_response = response.clone();
|
||||||
}
|
}
|
||||||
// Step 4
|
// Step 5
|
||||||
let mut response = response.unwrap();
|
let mut actual_response = Rc::try_unwrap(actual_response.unwrap()).ok().unwrap().into_inner();
|
||||||
match response.status.unwrap() {
|
let mut response = Rc::try_unwrap(response.unwrap()).ok().unwrap();
|
||||||
// Code 304
|
match actual_response.status.unwrap() {
|
||||||
StatusCode::NotModified => match self.cache_mode {
|
|
||||||
CacheMode::Default | CacheMode::NoCache => {
|
|
||||||
// TODO: Check HTTP cache for request and response entry
|
|
||||||
}
|
|
||||||
_ => { }
|
|
||||||
},
|
|
||||||
// Code 301, 302, 303, 307, 308
|
// Code 301, 302, 303, 307, 308
|
||||||
StatusCode::MovedPermanently | StatusCode::Found | StatusCode::SeeOther |
|
StatusCode::MovedPermanently | StatusCode::Found | StatusCode::SeeOther |
|
||||||
StatusCode::TemporaryRedirect | StatusCode::PermanentRedirect => {
|
StatusCode::TemporaryRedirect | StatusCode::PermanentRedirect => {
|
||||||
|
@ -321,19 +359,20 @@ impl Request {
|
||||||
return Response::network_error();
|
return Response::network_error();
|
||||||
}
|
}
|
||||||
// Step 2-4
|
// Step 2-4
|
||||||
if !response.headers.has::<Location>() {
|
if !actual_response.headers.has::<Location>() {
|
||||||
return response;
|
return actual_response;
|
||||||
}
|
}
|
||||||
let location = match response.headers.get::<Location>() {
|
let location = match actual_response.headers.get::<Location>() {
|
||||||
None => return Response::network_error(),
|
Some(&Location(ref location)) => location.clone(),
|
||||||
Some(location) => location,
|
_ => return Response::network_error(),
|
||||||
};
|
};
|
||||||
// Step 5
|
// Step 5
|
||||||
let location_url = Url::parse(location);
|
let location_url = UrlParser::new().base_url(self.url_list.last().unwrap()).parse(&*location);
|
||||||
// Step 6
|
// Step 6
|
||||||
let location_url = match location_url {
|
let location_url = match location_url {
|
||||||
|
Ok(ref url) if url.scheme == "data" => { return Response::network_error(); }
|
||||||
Ok(url) => url,
|
Ok(url) => url,
|
||||||
Err(_) => return Response::network_error()
|
_ => { return Response::network_error(); }
|
||||||
};
|
};
|
||||||
// Step 7
|
// Step 7
|
||||||
if self.redirect_count == 20 {
|
if self.redirect_count == 20 {
|
||||||
|
@ -341,62 +380,79 @@ impl Request {
|
||||||
}
|
}
|
||||||
// Step 8
|
// Step 8
|
||||||
self.redirect_count += 1;
|
self.redirect_count += 1;
|
||||||
|
match self.redirect_mode {
|
||||||
// Step 9
|
// Step 9
|
||||||
self.same_origin_data = false;
|
RedirectMode::Manual => {
|
||||||
|
*response.borrow_mut() = actual_response.to_filtered(ResponseType::Opaque);
|
||||||
|
}
|
||||||
// Step 10
|
// Step 10
|
||||||
if self.redirect_mode == RedirectMode::Follow {
|
RedirectMode::Follow => {
|
||||||
// FIXME: Origin method of the Url crate hasn't been implemented
|
|
||||||
// https://github.com/servo/rust-url/issues/54
|
|
||||||
|
|
||||||
// Substep 1
|
// Substep 1
|
||||||
// if cors_flag && location_url.origin() != self.url.origin() { self.origin = None; }
|
// FIXME: Use Url::origin
|
||||||
|
// if (self.mode == RequestMode::CORSMode || self.mode == RequestMode::ForcedPreflightMode) &&
|
||||||
|
// location_url.origin() != self.url.origin() &&
|
||||||
|
// has_credentials(&location_url) {
|
||||||
|
// return Response::network_error();
|
||||||
|
// }
|
||||||
// Substep 2
|
// Substep 2
|
||||||
if cors_flag && (!location_url.username().unwrap_or("").is_empty() ||
|
if cors_flag && has_credentials(&location_url) {
|
||||||
location_url.password().is_some()) {
|
|
||||||
return Response::network_error();
|
return Response::network_error();
|
||||||
}
|
}
|
||||||
// Substep 3
|
// Substep 3
|
||||||
if response.status.unwrap() == StatusCode::MovedPermanently ||
|
// FIXME: Use Url::origin
|
||||||
response.status.unwrap() == StatusCode::SeeOther ||
|
// if cors_flag && location_url.origin() != self.url.origin() {
|
||||||
(response.status.unwrap() == StatusCode::Found && self.method == Method::Post) {
|
// self.origin = Origin::UID(OpaqueOrigin);
|
||||||
|
// }
|
||||||
|
// Substep 4
|
||||||
|
if actual_response.status.unwrap() == StatusCode::SeeOther ||
|
||||||
|
((actual_response.status.unwrap() == StatusCode::MovedPermanently ||
|
||||||
|
actual_response.status.unwrap() == StatusCode::Found) &&
|
||||||
|
self.method == Method::Post) {
|
||||||
self.method = Method::Get;
|
self.method = Method::Get;
|
||||||
}
|
}
|
||||||
// Substep 4
|
|
||||||
self.url = location_url;
|
|
||||||
// Substep 5
|
// Substep 5
|
||||||
return self.fetch(cors_flag);
|
self.url_list.push(location_url);
|
||||||
|
// Substep 6
|
||||||
|
return self.main_fetch(cors_flag);
|
||||||
|
}
|
||||||
|
RedirectMode::Error => { panic!("RedirectMode is Error after step 8") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Code 401
|
// Code 401
|
||||||
StatusCode::Unauthorized => {
|
StatusCode::Unauthorized => {
|
||||||
// Step 1
|
// Step 1
|
||||||
if !self.authentication || cors_flag {
|
// FIXME: Figure out what to do with request window objects
|
||||||
return response;
|
if cors_flag {
|
||||||
|
return response.into_inner();
|
||||||
}
|
}
|
||||||
// Step 2
|
// Step 2
|
||||||
// TODO: Spec says requires testing
|
// TODO: Spec says requires testing on multiple WWW-Authenticate headers
|
||||||
// Step 3
|
// Step 3
|
||||||
if !self.use_url_credentials || authentication_fetch_flag {
|
if !self.use_url_credentials || authentication_fetch_flag {
|
||||||
// TODO: Prompt the user for username and password
|
// TODO: Prompt the user for username and password from the window
|
||||||
}
|
}
|
||||||
|
// Step 4
|
||||||
return self.http_fetch(cors_flag, cors_preflight_flag, true);
|
return self.http_fetch(cors_flag, cors_preflight_flag, true);
|
||||||
}
|
}
|
||||||
// Code 407
|
// Code 407
|
||||||
StatusCode::ProxyAuthenticationRequired => {
|
StatusCode::ProxyAuthenticationRequired => {
|
||||||
// Step 1
|
// Step 1
|
||||||
// TODO: Spec says requires testing
|
// TODO: Figure out what to do with request window objects
|
||||||
// Step 2
|
// Step 2
|
||||||
// TODO: Prompt the user for proxy authentication credentials
|
// TODO: Spec says requires testing on Proxy-Authenticate headers
|
||||||
// Step 3
|
// Step 3
|
||||||
|
// TODO: Prompt the user for proxy authentication credentials
|
||||||
|
// Step 4
|
||||||
return self.http_fetch(cors_flag, cors_preflight_flag, authentication_fetch_flag);
|
return self.http_fetch(cors_flag, cors_preflight_flag, authentication_fetch_flag);
|
||||||
}
|
}
|
||||||
_ => { }
|
_ => { }
|
||||||
}
|
}
|
||||||
// Step 5
|
let mut response = response.into_inner();
|
||||||
|
// Step 6
|
||||||
if authentication_fetch_flag {
|
if authentication_fetch_flag {
|
||||||
// TODO: Create authentication entry for this request
|
// TODO: Create authentication entry for this request
|
||||||
}
|
}
|
||||||
// Step 6
|
// Step 7
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,6 +477,10 @@ impl Request {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_credentials(url: &Url) -> bool {
|
||||||
|
!url.username().unwrap_or("").is_empty() || url.password().is_some()
|
||||||
|
}
|
||||||
|
|
||||||
fn is_no_store_cache(headers: &Headers) -> bool {
|
fn is_no_store_cache(headers: &Headers) -> bool {
|
||||||
headers.has::<IfModifiedSince>() | headers.has::<IfNoneMatch>() |
|
headers.has::<IfModifiedSince>() | headers.has::<IfNoneMatch>() |
|
||||||
headers.has::<IfUnmodifiedSince>() | headers.has::<IfMatch>() |
|
headers.has::<IfUnmodifiedSince>() | headers.has::<IfMatch>() |
|
||||||
|
|
|
@ -6,6 +6,8 @@ use hyper::header::Headers;
|
||||||
use hyper::status::StatusCode;
|
use hyper::status::StatusCode;
|
||||||
use net_traits::{Response, ResponseBody, ResponseType};
|
use net_traits::{Response, ResponseBody, ResponseType};
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::Receiver;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -20,6 +22,7 @@ impl ResponseMethods for Response {
|
||||||
response_type: ResponseType::Default,
|
response_type: ResponseType::Default,
|
||||||
termination_reason: None,
|
termination_reason: None,
|
||||||
url: None,
|
url: None,
|
||||||
|
url_list: Vec::new(),
|
||||||
status: Some(StatusCode::Ok),
|
status: Some(StatusCode::Ok),
|
||||||
headers: Headers::new(),
|
headers: Headers::new(),
|
||||||
body: ResponseBody::Empty,
|
body: ResponseBody::Empty,
|
||||||
|
@ -37,7 +40,7 @@ impl ResponseMethods for Response {
|
||||||
}
|
}
|
||||||
let old_headers = self.headers.clone();
|
let old_headers = self.headers.clone();
|
||||||
let mut response = self.clone();
|
let mut response = self.clone();
|
||||||
response.internal_response = Some(box self);
|
response.internal_response = Some(Rc::new(RefCell::new(self)));
|
||||||
match filter_type {
|
match filter_type {
|
||||||
ResponseType::Default | ResponseType::Error => unreachable!(),
|
ResponseType::Default | ResponseType::Error => unreachable!(),
|
||||||
ResponseType::Basic => {
|
ResponseType::Basic => {
|
||||||
|
@ -62,7 +65,8 @@ impl ResponseMethods for Response {
|
||||||
response.headers = headers;
|
response.headers = headers;
|
||||||
response.response_type = filter_type;
|
response.response_type = filter_type;
|
||||||
},
|
},
|
||||||
ResponseType::Opaque => {
|
ResponseType::Opaque |
|
||||||
|
ResponseType::OpaqueRedirect => {
|
||||||
response.headers = Headers::new();
|
response.headers = Headers::new();
|
||||||
response.status = None;
|
response.status = None;
|
||||||
response.body = ResponseBody::Empty;
|
response.body = ResponseBody::Empty;
|
||||||
|
|
|
@ -35,6 +35,8 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||||
use msg::constellation_msg::{PipelineId};
|
use msg::constellation_msg::{PipelineId};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserializer, Serializer};
|
use serde::{Deserializer, Serializer};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use util::mem::HeapSizeOf;
|
use util::mem::HeapSizeOf;
|
||||||
|
@ -55,7 +57,8 @@ pub enum ResponseType {
|
||||||
CORS,
|
CORS,
|
||||||
Default,
|
Default,
|
||||||
Error,
|
Error,
|
||||||
Opaque
|
Opaque,
|
||||||
|
OpaqueRedirect
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [Response termination reason](https://fetch.spec.whatwg.org/#concept-response-termination-reason)
|
/// [Response termination reason](https://fetch.spec.whatwg.org/#concept-response-termination-reason)
|
||||||
|
@ -87,13 +90,14 @@ pub struct Response {
|
||||||
pub response_type: ResponseType,
|
pub response_type: ResponseType,
|
||||||
pub termination_reason: Option<TerminationReason>,
|
pub termination_reason: Option<TerminationReason>,
|
||||||
pub url: Option<Url>,
|
pub url: Option<Url>,
|
||||||
|
pub url_list: Vec<Url>,
|
||||||
/// `None` can be considered a StatusCode of `0`.
|
/// `None` can be considered a StatusCode of `0`.
|
||||||
pub status: Option<StatusCode>,
|
pub status: Option<StatusCode>,
|
||||||
pub headers: Headers,
|
pub headers: Headers,
|
||||||
pub body: ResponseBody,
|
pub body: ResponseBody,
|
||||||
/// [Internal response](https://fetch.spec.whatwg.org/#concept-internal-response), only used if the Response
|
/// [Internal response](https://fetch.spec.whatwg.org/#concept-internal-response), only used if the Response
|
||||||
/// is a filtered response
|
/// is a filtered response
|
||||||
pub internal_response: Option<Box<Response>>,
|
pub internal_response: Option<Rc<RefCell<Response>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
|
@ -102,6 +106,7 @@ impl Response {
|
||||||
response_type: ResponseType::Error,
|
response_type: ResponseType::Error,
|
||||||
termination_reason: None,
|
termination_reason: None,
|
||||||
url: None,
|
url: None,
|
||||||
|
url_list: vec![],
|
||||||
status: None,
|
status: None,
|
||||||
headers: Headers::new(),
|
headers: Headers::new(),
|
||||||
body: ResponseBody::Empty,
|
body: ResponseBody::Empty,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue