mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05: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",
|
||||
"data-url",
|
||||
"deno_core",
|
||||
"deno_file",
|
||||
"http",
|
||||
"reqwest",
|
||||
"serde",
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -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::<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))),
|
||||
};
|
||||
|
||||
|
|
|
@ -24,9 +24,10 @@ pub struct Location(pub Url);
|
|||
pub struct BlobUrlStore(Arc<Mutex<HashMap<Url, Blob>>>);
|
||||
|
||||
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();
|
||||
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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue