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:
Luca Casonato 2021-04-11 14:09:10 +02:00 committed by GitHub
parent f5a9474952
commit e7f18d6468
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 40 additions and 5 deletions

1
Cargo.lock generated
View file

@ -626,6 +626,7 @@ dependencies = [
"bytes",
"data-url",
"deno_core",
"deno_file",
"http",
"reqwest",
"serde",

View file

@ -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),

View file

@ -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"] }

View file

@ -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))),
};

View file

@ -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 {

View file

@ -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,