0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

feat: data URL support in fetch (#10054)

This commit adds data URL support in `fetch`. Tested via wpt.
This commit is contained in:
Luca Casonato 2021-04-10 23:38:15 +02:00 committed by GitHub
parent 8d55d8b6be
commit 3ab94983b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 37 deletions

11
Cargo.lock generated
View file

@ -498,6 +498,15 @@ version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
[[package]]
name = "data-url"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d33fe99ccedd6e84bc035f1931bb2e6be79739d6242bd895e7311c886c50dc9c"
dependencies = [
"matches",
]
[[package]]
name = "deno"
version = "1.8.3"
@ -615,7 +624,9 @@ name = "deno_fetch"
version = "0.24.1"
dependencies = [
"bytes",
"data-url",
"deno_core",
"http",
"reqwest",
"serde",
"tokio",

View file

@ -15,7 +15,9 @@ path = "lib.rs"
[dependencies]
bytes = "1.0.1"
data-url = "0.1.0"
deno_core = { version = "0.83.0", path = "../../core" }
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"] }
tokio = { version = "1.4.0", features = ["full"] }

View file

@ -2,6 +2,7 @@
#![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;
@ -157,52 +158,76 @@ where
// Check scheme before asking for net permission
let scheme = url.scheme();
if scheme != "http" && scheme != "https" {
return Err(type_error(format!("scheme '{}' not supported", scheme)));
}
let (request_rid, request_body_rid) = match scheme {
"http" | "https" => {
let permissions = state.borrow::<FP>();
permissions.check_net_url(&url)?;
let permissions = state.borrow::<FP>();
permissions.check_net_url(&url)?;
let mut request = client.request(method, url);
let mut request = client.request(method, url);
let request_body_rid = if args.has_body {
match data {
None => {
// If no body is passed, we return a writer for streaming the body.
let (tx, rx) = mpsc::channel::<std::io::Result<Vec<u8>>>(1);
request = request.body(Body::wrap_stream(ReceiverStream::new(rx)));
let request_body_rid = if args.has_body {
match data {
None => {
// If no body is passed, we return a writer for streaming the body.
let (tx, rx) = mpsc::channel::<std::io::Result<Vec<u8>>>(1);
request = request.body(Body::wrap_stream(ReceiverStream::new(rx)));
let request_body_rid =
state.resource_table.add(FetchRequestBodyResource {
body: AsyncRefCell::new(tx),
cancel: CancelHandle::default(),
});
let request_body_rid =
state.resource_table.add(FetchRequestBodyResource {
body: AsyncRefCell::new(tx),
cancel: CancelHandle::default(),
});
Some(request_body_rid)
}
Some(data) => {
// If a body is passed, we use it, and don't return a body for streaming.
request = request.body(Vec::from(&*data));
Some(request_body_rid)
}
Some(data) => {
// If a body is passed, we use it, and don't return a body for streaming.
request = request.body(Vec::from(&*data));
None
}
}
} else {
None
};
for (key, value) in args.headers {
let name = HeaderName::from_bytes(key.as_bytes()).unwrap();
let v = HeaderValue::from_str(&value).unwrap();
request = request.header(name, v);
}
let fut = request.send();
let request_rid = state
.resource_table
.add(FetchRequestResource(Box::pin(fut)));
(request_rid, request_body_rid)
}
} else {
None
"data" => {
let data_url = DataUrl::process(url.as_str())
.map_err(|e| type_error(format!("{:?}", e)))?;
let (body, _) = data_url
.decode_to_vec()
.map_err(|e| type_error(format!("{:?}", e)))?;
let response = http::Response::builder()
.status(http::StatusCode::OK)
.header(http::header::CONTENT_TYPE, data_url.mime_type().to_string())
.body(reqwest::Body::from(body))?;
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))),
};
for (key, value) in args.headers {
let name = HeaderName::from_bytes(key.as_bytes()).unwrap();
let v = HeaderValue::from_str(&value).unwrap();
request = request.header(name, v);
}
let fut = request.send();
let request_rid = state
.resource_table
.add(FetchRequestResource(Box::pin(fut)));
Ok(FetchReturn {
request_rid,
request_body_rid,

View file

@ -768,6 +768,13 @@
"Check isHistoryNavigation attribute"
]
}
},
"data-urls": {
"base64.any.js": true,
"processing.any.js": [
"\"data://test:test/,X\"",
"\"data:text/plain;a=\\\",\\\",X\""
]
}
},
"FileAPI": {