diff options
Diffstat (limited to 'runtime/ops/web_worker')
-rw-r--r-- | runtime/ops/web_worker/sync_fetch.rs | 95 |
1 files changed, 57 insertions, 38 deletions
diff --git a/runtime/ops/web_worker/sync_fetch.rs b/runtime/ops/web_worker/sync_fetch.rs index cdb151a86..d1f133d3d 100644 --- a/runtime/ops/web_worker/sync_fetch.rs +++ b/runtime/ops/web_worker/sync_fetch.rs @@ -4,15 +4,13 @@ use std::sync::Arc; use crate::web_worker::WebWorkerInternalHandle; use crate::web_worker::WebWorkerType; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::futures::StreamExt; use deno_core::op2; use deno_core::url::Url; use deno_core::OpState; use deno_fetch::data_url::DataUrl; +use deno_fetch::FetchError; use deno_web::BlobStore; -use deno_websocket::DomExceptionNetworkError; use http_body_util::BodyExt; use hyper::body::Bytes; use serde::Deserialize; @@ -27,6 +25,32 @@ fn mime_type_essence(mime_type: &str) -> String { essence.trim().to_ascii_lowercase() } +#[derive(Debug, thiserror::Error)] +pub enum SyncFetchError { + #[error("Blob URLs are not supported in this context.")] + BlobUrlsNotSupportedInContext, + #[error("{0}")] + Io(#[from] std::io::Error), + #[error("Invalid script URL")] + InvalidScriptUrl, + #[error("http status error: {0}")] + InvalidStatusCode(http::StatusCode), + #[error("Classic scripts with scheme {0}: are not supported in workers")] + ClassicScriptSchemeUnsupportedInWorkers(String), + #[error("{0}")] + InvalidUri(#[from] http::uri::InvalidUri), + #[error("Invalid MIME type {0:?}.")] + InvalidMimeType(String), + #[error("Missing MIME type.")] + MissingMimeType, + #[error(transparent)] + Fetch(#[from] FetchError), + #[error(transparent)] + Join(#[from] tokio::task::JoinError), + #[error(transparent)] + Other(deno_core::error::AnyError), +} + #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SyncFetchScript { @@ -40,21 +64,22 @@ pub fn op_worker_sync_fetch( state: &mut OpState, #[serde] scripts: Vec<String>, loose_mime_checks: bool, -) -> Result<Vec<SyncFetchScript>, AnyError> { +) -> Result<Vec<SyncFetchScript>, SyncFetchError> { let handle = state.borrow::<WebWorkerInternalHandle>().clone(); assert_eq!(handle.worker_type, WebWorkerType::Classic); // it's not safe to share a client across tokio runtimes, so create a fresh one // https://github.com/seanmonstar/reqwest/issues/1148#issuecomment-910868788 let options = state.borrow::<deno_fetch::Options>().clone(); - let client = deno_fetch::create_client_from_options(&options)?; + let client = deno_fetch::create_client_from_options(&options) + .map_err(FetchError::ClientCreate)?; // TODO(andreubotella) It's not good to throw an exception related to blob // URLs when none of the script URLs use the blob scheme. // Also, in which contexts are blob URLs not supported? let blob_store = state .try_borrow::<Arc<BlobStore>>() - .ok_or_else(|| type_error("Blob URLs are not supported in this context."))? + .ok_or(SyncFetchError::BlobUrlsNotSupportedInContext)? .clone(); // TODO(andreubotella): make the below thread into a resource that can be @@ -74,7 +99,7 @@ pub fn op_worker_sync_fetch( let blob_store = blob_store.clone(); deno_core::unsync::spawn(async move { let script_url = Url::parse(&script) - .map_err(|_| type_error("Invalid script URL"))?; + .map_err(|_| SyncFetchError::InvalidScriptUrl)?; let mut loose_mime_checks = loose_mime_checks; let (body, mime_type, res_url) = match script_url.scheme() { @@ -86,15 +111,13 @@ pub fn op_worker_sync_fetch( ); *req.uri_mut() = script_url.as_str().parse()?; - let resp = client.send(req).await?; + let resp = + client.send(req).await.map_err(FetchError::ClientSend)?; if resp.status().is_client_error() || resp.status().is_server_error() { - return Err(type_error(format!( - "http status error: {}", - resp.status() - ))); + return Err(SyncFetchError::InvalidStatusCode(resp.status())); } // TODO(andreubotella) Properly run fetch's "extract a MIME type". @@ -107,42 +130,45 @@ pub fn op_worker_sync_fetch( // Always check the MIME type with HTTP(S). loose_mime_checks = false; - let body = resp.collect().await?.to_bytes(); + let body = resp + .collect() + .await + .map_err(SyncFetchError::Other)? + .to_bytes(); (body, mime_type, script) } "data" => { - let data_url = DataUrl::process(&script) - .map_err(|e| type_error(format!("{e:?}")))?; + let data_url = + DataUrl::process(&script).map_err(FetchError::DataUrl)?; let mime_type = { let mime = data_url.mime_type(); format!("{}/{}", mime.type_, mime.subtype) }; - let (body, _) = data_url - .decode_to_vec() - .map_err(|e| type_error(format!("{e:?}")))?; + let (body, _) = + data_url.decode_to_vec().map_err(FetchError::Base64)?; (Bytes::from(body), Some(mime_type), script) } "blob" => { - let blob = - blob_store.get_object_url(script_url).ok_or_else(|| { - type_error("Blob for the given URL not found.") - })?; + let blob = blob_store + .get_object_url(script_url) + .ok_or(FetchError::BlobNotFound)?; let mime_type = mime_type_essence(&blob.media_type); - let body = blob.read_all().await?; + let body = blob.read_all().await; (Bytes::from(body), Some(mime_type), script) } _ => { - return Err(type_error(format!( - "Classic scripts with scheme {}: are not supported in workers.", - script_url.scheme() - ))) + return Err( + SyncFetchError::ClassicScriptSchemeUnsupportedInWorkers( + script_url.scheme().to_string(), + ), + ) } }; @@ -151,18 +177,11 @@ pub fn op_worker_sync_fetch( match mime_type.as_deref() { Some("application/javascript" | "text/javascript") => {} Some(mime_type) => { - return Err( - DomExceptionNetworkError { - msg: format!("Invalid MIME type {mime_type:?}."), - } - .into(), - ) - } - None => { - return Err( - DomExceptionNetworkError::new("Missing MIME type.").into(), - ) + return Err(SyncFetchError::InvalidMimeType( + mime_type.to_string(), + )) } + None => return Err(SyncFetchError::MissingMimeType), } } |