summaryrefslogtreecommitdiff
path: root/ext/fetch/lib.rs
diff options
context:
space:
mode:
authorAndreu Botella <abb@randomunok.com>2021-09-08 11:29:21 +0200
committerGitHub <noreply@github.com>2021-09-08 11:29:21 +0200
commit1563088f060b1f1d4826bb3a6d4120b276a4e15f (patch)
treeff8b406511f0e7322a55e32d5272298ea4a061b5 /ext/fetch/lib.rs
parente07f28d301b990ebf534cbb8d5fa9f507475c89f (diff)
fix: a `Request` whose URL is a revoked blob URL should still fetch (#11947)
In the spec, a URL record has an associated "blob URL entry", which for `blob:` URLs is populated during parsing to contain a reference to the `Blob` object that backs that object URL. It is this blob URL entry that the `fetch` API uses to resolve an object URL. Therefore, since the `Request` constructor parses URL inputs, it will have an associated blob URL entry which will be used when fetching, even if the object URL has been revoked since the construction of the `Request` object. (The `Request` constructor takes the URL as a string and parses it, so the object URL must be live at the time it is called.) This PR adds a new `blobFromObjectUrl` JS function (backed by a new `op_blob_from_object_url` op) that, if the URL is a valid object URL, returns a new `Blob` object whose parts are references to the same Rust `BlobPart`s used by the original `Blob` object. It uses this function to add a new `blobUrlEntry` field to inner requests, which will be `null` or such a `Blob`, and then uses `Blob.prototype.stream()` as the response's body. As a result of this, the `blob:` URL resolution from `op_fetch` is now useless, and has been removed.
Diffstat (limited to 'ext/fetch/lib.rs')
-rw-r--r--ext/fetch/lib.rs47
1 files changed, 3 insertions, 44 deletions
diff --git a/ext/fetch/lib.rs b/ext/fetch/lib.rs
index c419180c5..70ed40358 100644
--- a/ext/fetch/lib.rs
+++ b/ext/fetch/lib.rs
@@ -26,7 +26,6 @@ use deno_core::ZeroCopyBuf;
use deno_tls::create_http_client;
use deno_tls::rustls::RootCertStore;
use deno_tls::Proxy;
-use deno_web::BlobStore;
use http::header::CONTENT_LENGTH;
use reqwest::header::HeaderName;
use reqwest::header::HeaderValue;
@@ -275,49 +274,9 @@ where
(request_rid, None, None)
}
"blob" => {
- let blob_store = state.try_borrow::<BlobStore>().ok_or_else(|| {
- type_error("Blob URLs are not supported in this context.")
- })?;
-
- let blob = blob_store
- .get_object_url(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 cancel_handle = CancelHandle::new_rc();
- let cancel_handle_ = cancel_handle.clone();
-
- let fut = async move {
- // TODO(lucacsonato): this should be a stream!
- let chunk = match blob.read_all().or_cancel(cancel_handle_).await? {
- Ok(chunk) => chunk,
- Err(err) => return Ok(Err(err)),
- };
-
- let res = http::Response::builder()
- .status(http::StatusCode::OK)
- .header(http::header::CONTENT_LENGTH, chunk.len())
- .header(http::header::CONTENT_TYPE, blob.media_type.clone())
- .body(reqwest::Body::from(chunk))
- .map_err(|err| type_error(err.to_string()));
-
- match res {
- Ok(response) => Ok(Ok(Response::from(response))),
- Err(err) => Ok(Err(err)),
- }
- };
-
- let request_rid = state
- .resource_table
- .add(FetchRequestResource(Box::pin(fut)));
-
- let cancel_handle_rid =
- state.resource_table.add(FetchCancelHandle(cancel_handle));
-
- (request_rid, None, Some(cancel_handle_rid))
+ // Blob URL resolution happens in the JS side of fetch. If we got here is
+ // because the URL isn't an object URL.
+ return Err(type_error("Blob for the given URL not found."));
}
_ => return Err(type_error(format!("scheme '{}' not supported", scheme))),
};