diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs index 0a41f930128..2a2753a55c9 100644 --- a/components/net/fetch/methods.rs +++ b/components/net/fetch/methods.rs @@ -274,10 +274,12 @@ pub async fn main_fetch( // Step 12. + let current_url = request.current_url(); + let current_scheme = current_url.scheme(); + let mut response = match response { Some(res) => res, None => { - let current_url = request.current_url(); let same_origin = if let Origin::Origin(ref origin) = request.origin { *origin == current_url.origin() } else { @@ -285,8 +287,8 @@ pub async fn main_fetch( }; if (same_origin && !cors_flag) || - current_url.scheme() == "data" || - current_url.scheme() == "chrome" || + current_scheme == "chrome" || + context.protocols.is_fetchable(current_scheme) || matches!( request.mode, RequestMode::Navigate | RequestMode::WebSocket { .. } @@ -312,7 +314,7 @@ pub async fn main_fetch( // Substep 3. Return the result of running scheme fetch given fetchParams. scheme_fetch(request, cache, target, done_chan, context).await } - } else if !matches!(current_url.scheme(), "http" | "https") { + } else if !matches!(current_scheme, "http" | "https") { Response::network_error(NetworkError::Internal("Non-http scheme".into())) } else if request.use_cors_preflight || (request.unsafe_request && @@ -494,7 +496,7 @@ pub async fn main_fetch( } // Step 21. - if request.body.is_some() && matches!(request.current_url().scheme(), "http" | "https") { + if request.body.is_some() && matches!(current_scheme, "http" | "https") { // XXXManishearth: We actually should be calling process_request // in http_network_fetch. However, we can't yet follow the request // upload progress, so I'm keeping it here for now and pretending diff --git a/components/net/protocols/data.rs b/components/net/protocols/data.rs index 0f548683373..e154d8226ec 100644 --- a/components/net/protocols/data.rs +++ b/components/net/protocols/data.rs @@ -54,4 +54,8 @@ impl ProtocolHandler for DataProtocolHander { Box::pin(std::future::ready(response)) } + + fn is_fetchable(&self) -> bool { + true + } } diff --git a/components/net/protocols/mod.rs b/components/net/protocols/mod.rs index ea64bfcd389..77d7d04a26b 100644 --- a/components/net/protocols/mod.rs +++ b/components/net/protocols/mod.rs @@ -29,12 +29,24 @@ use file::FileProtocolHander; static FORBIDDEN_SCHEMES: [&str; 4] = ["http", "https", "chrome", "about"]; pub trait ProtocolHandler: Send + Sync { + /// Triggers the load of a resource for this protocol and returns a future + /// that will produce a Response. Even if the protocol is not backed by a + /// http endpoint, it is recommended to a least provide: + /// - A relevant status code. + /// - A Content Type. fn load( &self, request: &mut Request, done_chan: &mut DoneChannel, context: &FetchContext, ) -> Pin + Send>>; + + /// Specify if resources served by that protocol can be retrieved + /// with `fetch()` without no-cors mode to allow the caller direct + /// access to the resource content. + fn is_fetchable(&self) -> bool { + false + } } #[derive(Default)] @@ -80,6 +92,13 @@ impl ProtocolRegistry { self.handlers.entry(scheme).or_insert(handler); } } + + pub fn is_fetchable(&self, scheme: &str) -> bool { + self.handlers + .get(scheme) + .map(|handler| handler.is_fetchable()) + .unwrap_or(false) + } } pub fn range_not_satisfiable_error(response: &mut Response) { diff --git a/ports/servoshell/desktop/protocols/urlinfo.rs b/ports/servoshell/desktop/protocols/urlinfo.rs index 38c2461bccd..7671b27a4e8 100644 --- a/ports/servoshell/desktop/protocols/urlinfo.rs +++ b/ports/servoshell/desktop/protocols/urlinfo.rs @@ -43,4 +43,8 @@ impl ProtocolHandler for UrlInfoProtocolHander { Box::pin(std::future::ready(response)) } + + fn is_fetchable(&self) -> bool { + true + } }