diff --git a/Cargo.lock b/Cargo.lock index 203c90c194..c77f132149 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -626,6 +626,7 @@ dependencies = [ "bytes", "data-url", "deno_core", + "deno_file", "http", "reqwest", "serde", diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs index 3e4332b241..187ac05dcc 100644 --- a/cli/file_fetcher.rs +++ b/cli/file_fetcher.rs @@ -475,7 +475,7 @@ impl FileFetcher { } let blob_url_storage = self.blob_url_store.borrow(); - let blob = blob_url_storage.get(specifier)?.ok_or_else(|| { + let blob = blob_url_storage.get(specifier.clone())?.ok_or_else(|| { custom_error( "NotFound", format!("Blob URL not found: \"{}\".", specifier), diff --git a/op_crates/fetch/Cargo.toml b/op_crates/fetch/Cargo.toml index b61a1ffa37..1a2baa3146 100644 --- a/op_crates/fetch/Cargo.toml +++ b/op_crates/fetch/Cargo.toml @@ -17,6 +17,7 @@ path = "lib.rs" bytes = "1.0.1" data-url = "0.1.0" deno_core = { version = "0.83.0", path = "../../core" } +deno_file = { version = "0.1.0", path = "../file" } http = "0.2.3" reqwest = { version = "0.11.2", default-features = false, features = ["rustls-tls", "stream", "gzip", "brotli"] } serde = { version = "1.0.125", features = ["derive"] } diff --git a/op_crates/fetch/lib.rs b/op_crates/fetch/lib.rs index b3e258e5e4..69c0c46ad7 100644 --- a/op_crates/fetch/lib.rs +++ b/op_crates/fetch/lib.rs @@ -2,7 +2,6 @@ #![deny(warnings)] -use data_url::DataUrl; use deno_core::error::bad_resource_id; use deno_core::error::generic_error; use deno_core::error::null_opbuf; @@ -23,6 +22,8 @@ use deno_core::Resource; use deno_core::ResourceId; use deno_core::ZeroCopyBuf; +use data_url::DataUrl; +use deno_file::BlobUrlStore; use reqwest::header::HeaderMap; use reqwest::header::HeaderName; use reqwest::header::HeaderValue; @@ -225,6 +226,34 @@ where (request_rid, None) } + "blob" => { + let blob_url_storage = + state.try_borrow::().ok_or_else(|| { + type_error("Blob URLs are not supported in this context.") + })?; + + let blob = blob_url_storage + .get(url)? + .ok_or_else(|| type_error("Blob for the given URL not found."))?; + + if method != "GET" { + return Err(type_error("Blob URL fetch only supports GET method.")); + } + + let response = http::Response::builder() + .status(http::StatusCode::OK) + .header(http::header::CONTENT_LENGTH, blob.data.len()) + .header(http::header::CONTENT_TYPE, blob.media_type) + .body(reqwest::Body::from(blob.data))?; + + let fut = async move { Ok(Response::from(response)) }; + + let request_rid = state + .resource_table + .add(FetchRequestResource(Box::pin(fut))); + + (request_rid, None) + } _ => return Err(type_error(format!("scheme '{}' not supported", scheme))), }; diff --git a/op_crates/file/lib.rs b/op_crates/file/lib.rs index e8c2cde1d6..ea519046f1 100644 --- a/op_crates/file/lib.rs +++ b/op_crates/file/lib.rs @@ -24,9 +24,10 @@ pub struct Location(pub Url); pub struct BlobUrlStore(Arc>>); impl BlobUrlStore { - pub fn get(&self, url: &ModuleSpecifier) -> Result, AnyError> { + pub fn get(&self, mut url: Url) -> Result, AnyError> { let blob_store = self.0.lock().unwrap(); - Ok(blob_store.get(url).cloned()) + url.set_fragment(None); + Ok(blob_store.get(&url).cloned()) } pub fn insert(&self, blob: Blob, maybe_location: Option) -> Url { diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json index a7eca6f79b..520ed3b013 100644 --- a/tools/wpt/expectation.json +++ b/tools/wpt/expectation.json @@ -793,7 +793,10 @@ }, "fileReader.any.js": true, "url": { - "url-format.any.js": true + "url-format.any.js": true, + "url-with-fetch.any.js": [ + "Revoke blob URL after creating Request, will fetch" + ] }, "reading-data-section": { "Determining-Encoding.any.js": true,