Skip to content

Commit

Permalink
fix: fallback to default UA and CA data for Deno.createHttpClient() (d…
Browse files Browse the repository at this point in the history
  • Loading branch information
AaronO committed Mar 18, 2021
1 parent fb5a278 commit 7d12dd1
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 57 deletions.
21 changes: 21 additions & 0 deletions cli/tests/unit/fetch_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,27 @@ MNf4EgWfK+tZMnuqfpfO9740KzfcVoMNo4QJD4yn5YxroUOO/Azi
},
);

unitTest(
{ perms: { net: true } },
async function fetchCustomClientUserAgent(): Promise<
void
> {
const data = "Hello World";
const client = Deno.createHttpClient({});
const response = await fetch("http:https://localhost:4545/echo_server", {
client,
method: "POST",
body: new TextEncoder().encode(data),
});
assertEquals(
response.headers.get("user-agent"),
`Deno/${Deno.version.deno}`,
);
await response.text();
client.close();
},
);

unitTest(
{
perms: { net: true },
Expand Down
53 changes: 41 additions & 12 deletions op_crates/fetch/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ use deno_core::RcRef;
use deno_core::Resource;
use deno_core::ZeroCopyBuf;

use reqwest::header::HeaderMap;
use reqwest::header::HeaderName;
use reqwest::header::HeaderValue;
use reqwest::header::USER_AGENT;
use reqwest::redirect::Policy;
use reqwest::Body;
use reqwest::Client;
Expand Down Expand Up @@ -80,6 +82,11 @@ pub fn init(isolate: &mut JsRuntime) {
}
}

pub struct HttpClientDefaults {
pub user_agent: String,
pub ca_data: Option<Vec<u8>>,
}

pub trait FetchPermissions {
fn check_net_url(&self, _url: &Url) -> Result<(), AnyError>;
fn check_read(&self, _p: &Path) -> Result<(), AnyError>;
Expand Down Expand Up @@ -399,31 +406,53 @@ where
permissions.check_read(&PathBuf::from(ca_file))?;
}

let client =
create_http_client(args.ca_file.as_deref(), args.ca_data.as_deref())
.unwrap();
let defaults = state.borrow::<HttpClientDefaults>();

let cert_data =
get_cert_data(args.ca_file.as_deref(), args.ca_data.as_deref())?;
let client = create_http_client(
defaults.user_agent.clone(),
cert_data.or_else(|| defaults.ca_data.clone()),
)
.unwrap();

let rid = state.resource_table.add(HttpClientResource::new(client));
Ok(json!(rid))
}

/// Create new instance of async reqwest::Client. This client supports
/// proxies and doesn't follow redirects.
fn create_http_client(
fn get_cert_data(
ca_file: Option<&str>,
ca_data: Option<&str>,
) -> Result<Client, AnyError> {
let mut builder = Client::builder().redirect(Policy::none()).use_rustls_tls();
) -> Result<Option<Vec<u8>>, AnyError> {
if let Some(ca_data) = ca_data {
let ca_data_vec = ca_data.as_bytes().to_vec();
let cert = reqwest::Certificate::from_pem(&ca_data_vec)?;
builder = builder.add_root_certificate(cert);
Ok(Some(ca_data.as_bytes().to_vec()))
} else if let Some(ca_file) = ca_file {
let mut buf = Vec::new();
File::open(ca_file)?.read_to_end(&mut buf)?;
let cert = reqwest::Certificate::from_pem(&buf)?;
Ok(Some(buf))
} else {
Ok(None)
}
}

/// Create new instance of async reqwest::Client. This client supports
/// proxies and doesn't follow redirects.
pub fn create_http_client(
user_agent: String,
ca_data: Option<Vec<u8>>,
) -> Result<Client, AnyError> {
let mut headers = HeaderMap::new();
headers.insert(USER_AGENT, user_agent.parse().unwrap());
let mut builder = Client::builder()
.redirect(Policy::none())
.default_headers(headers)
.use_rustls_tls();

if let Some(ca_data) = ca_data {
let cert = reqwest::Certificate::from_pem(&ca_data)?;
builder = builder.add_root_certificate(cert);
}

builder
.build()
.map_err(|e| generic_error(format!("Unable to build http client: {}", e)))
Expand Down
42 changes: 0 additions & 42 deletions runtime/http_util.rs

This file was deleted.

1 change: 0 additions & 1 deletion runtime/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ pub use deno_websocket;
pub mod colors;
pub mod errors;
pub mod fs_util;
pub mod http_util;
pub mod inspector;
pub mod js;
pub mod metrics;
Expand Down
9 changes: 7 additions & 2 deletions runtime/ops/fetch.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use crate::http_util;
use crate::permissions::Permissions;
use deno_fetch::reqwest;
use deno_fetch::HttpClientDefaults;

pub fn init(
rt: &mut deno_core::JsRuntime,
Expand All @@ -12,7 +12,12 @@ pub fn init(
let op_state = rt.op_state();
let mut state = op_state.borrow_mut();
state.put::<reqwest::Client>({
http_util::create_http_client(user_agent, ca_data).unwrap()
deno_fetch::create_http_client(user_agent.clone(), ca_data.clone())
.unwrap()
});
state.put::<HttpClientDefaults>(HttpClientDefaults {
ca_data,
user_agent,
});
}
super::reg_json_sync(rt, "op_fetch", deno_fetch::op_fetch::<Permissions>);
Expand Down

0 comments on commit 7d12dd1

Please sign in to comment.