diff options
author | Luca Casonato <lucacasonato@yahoo.com> | 2021-04-10 23:38:15 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-10 23:38:15 +0200 |
commit | 3ab94983b4100d5ae3c1d99c8b6a580510cd83f5 (patch) | |
tree | 1849d6873ec09ff8812b23ca36db9077022cf2e9 /op_crates/fetch/lib.rs | |
parent | 8d55d8b6be8731d37ccf6a29127b3a91a8319d0b (diff) |
feat: data URL support in fetch (#10054)
This commit adds data URL support in `fetch`. Tested via wpt.
Diffstat (limited to 'op_crates/fetch/lib.rs')
-rw-r--r-- | op_crates/fetch/lib.rs | 99 |
1 files changed, 62 insertions, 37 deletions
diff --git a/op_crates/fetch/lib.rs b/op_crates/fetch/lib.rs index 32a5a0140..b3e258e5e 100644 --- a/op_crates/fetch/lib.rs +++ b/op_crates/fetch/lib.rs @@ -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,51 +158,75 @@ 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 permissions = state.borrow::<FP>(); - permissions.check_net_url(&url)?; + let (request_rid, request_body_rid) = match scheme { + "http" | "https" => { + let permissions = state.borrow::<FP>(); + permissions.check_net_url(&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 = + 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)); + None + } + } + } else { + None + }; - let mut request = client.request(method, url); + 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 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 fut = request.send(); - let request_body_rid = - state.resource_table.add(FetchRequestBodyResource { - body: AsyncRefCell::new(tx), - cancel: CancelHandle::default(), - }); + let request_rid = state + .resource_table + .add(FetchRequestResource(Box::pin(fut))); - 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 - } + (request_rid, request_body_rid) } - } else { - None - }; + "data" => { + let data_url = DataUrl::process(url.as_str()) + .map_err(|e| type_error(format!("{:?}", e)))?; - 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 (body, _) = data_url + .decode_to_vec() + .map_err(|e| type_error(format!("{:?}", e)))?; - let fut = request.send(); + 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 request_rid = state - .resource_table - .add(FetchRequestResource(Box::pin(fut))); + 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))), + }; Ok(FetchReturn { request_rid, |