mirror of
https://github.com/denoland/deno.git
synced 2025-09-28 13:14:48 +00:00
feat: blob URL support in fetch (#10120)
This commit adds blob URL support in `fetch`. Tested via WPT. This is the first op_crate to have a rust dependency on a different op_crate.
This commit is contained in:
parent
f5a9474952
commit
e7f18d6468
6 changed files with 40 additions and 5 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -626,6 +626,7 @@ dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"data-url",
|
"data-url",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
"deno_file",
|
||||||
"http",
|
"http",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
@ -475,7 +475,7 @@ impl FileFetcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
let blob_url_storage = self.blob_url_store.borrow();
|
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(
|
custom_error(
|
||||||
"NotFound",
|
"NotFound",
|
||||||
format!("Blob URL not found: \"{}\".", specifier),
|
format!("Blob URL not found: \"{}\".", specifier),
|
||||||
|
|
|
@ -17,6 +17,7 @@ path = "lib.rs"
|
||||||
bytes = "1.0.1"
|
bytes = "1.0.1"
|
||||||
data-url = "0.1.0"
|
data-url = "0.1.0"
|
||||||
deno_core = { version = "0.83.0", path = "../../core" }
|
deno_core = { version = "0.83.0", path = "../../core" }
|
||||||
|
deno_file = { version = "0.1.0", path = "../file" }
|
||||||
http = "0.2.3"
|
http = "0.2.3"
|
||||||
reqwest = { version = "0.11.2", default-features = false, features = ["rustls-tls", "stream", "gzip", "brotli"] }
|
reqwest = { version = "0.11.2", default-features = false, features = ["rustls-tls", "stream", "gzip", "brotli"] }
|
||||||
serde = { version = "1.0.125", features = ["derive"] }
|
serde = { version = "1.0.125", features = ["derive"] }
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
|
|
||||||
use data_url::DataUrl;
|
|
||||||
use deno_core::error::bad_resource_id;
|
use deno_core::error::bad_resource_id;
|
||||||
use deno_core::error::generic_error;
|
use deno_core::error::generic_error;
|
||||||
use deno_core::error::null_opbuf;
|
use deno_core::error::null_opbuf;
|
||||||
|
@ -23,6 +22,8 @@ use deno_core::Resource;
|
||||||
use deno_core::ResourceId;
|
use deno_core::ResourceId;
|
||||||
use deno_core::ZeroCopyBuf;
|
use deno_core::ZeroCopyBuf;
|
||||||
|
|
||||||
|
use data_url::DataUrl;
|
||||||
|
use deno_file::BlobUrlStore;
|
||||||
use reqwest::header::HeaderMap;
|
use reqwest::header::HeaderMap;
|
||||||
use reqwest::header::HeaderName;
|
use reqwest::header::HeaderName;
|
||||||
use reqwest::header::HeaderValue;
|
use reqwest::header::HeaderValue;
|
||||||
|
@ -225,6 +226,34 @@ where
|
||||||
|
|
||||||
(request_rid, None)
|
(request_rid, None)
|
||||||
}
|
}
|
||||||
|
"blob" => {
|
||||||
|
let blob_url_storage =
|
||||||
|
state.try_borrow::<BlobUrlStore>().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))),
|
_ => return Err(type_error(format!("scheme '{}' not supported", scheme))),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,10 @@ pub struct Location(pub Url);
|
||||||
pub struct BlobUrlStore(Arc<Mutex<HashMap<Url, Blob>>>);
|
pub struct BlobUrlStore(Arc<Mutex<HashMap<Url, Blob>>>);
|
||||||
|
|
||||||
impl BlobUrlStore {
|
impl BlobUrlStore {
|
||||||
pub fn get(&self, url: &ModuleSpecifier) -> Result<Option<Blob>, AnyError> {
|
pub fn get(&self, mut url: Url) -> Result<Option<Blob>, AnyError> {
|
||||||
let blob_store = self.0.lock().unwrap();
|
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>) -> Url {
|
pub fn insert(&self, blob: Blob, maybe_location: Option<Url>) -> Url {
|
||||||
|
|
|
@ -793,7 +793,10 @@
|
||||||
},
|
},
|
||||||
"fileReader.any.js": true,
|
"fileReader.any.js": true,
|
||||||
"url": {
|
"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": {
|
"reading-data-section": {
|
||||||
"Determining-Encoding.any.js": true,
|
"Determining-Encoding.any.js": true,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue