From 4f1b1903cfadeeba24e1b0448879fe12682effb9 Mon Sep 17 00:00:00 2001 From: Tomofumi Chiba Date: Tue, 22 Jun 2021 12:21:57 +0900 Subject: feat(fetch): add programmatic proxy (#10907) This commit adds new options to unstable "Deno.createHttpClient" API. "proxy" and "basicAuth" options were added that allow to use custom proxy when client instance is passed to "fetch" API. --- extensions/fetch/lib.rs | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (limited to 'extensions/fetch/lib.rs') diff --git a/extensions/fetch/lib.rs b/extensions/fetch/lib.rs index cdac0d64c..3652c8724 100644 --- a/extensions/fetch/lib.rs +++ b/extensions/fetch/lib.rs @@ -56,6 +56,7 @@ pub use reqwest; // Re-export reqwest pub fn init( user_agent: String, ca_data: Option>, + proxy: Option, ) -> Extension { Extension::builder() .js(include_js_files!( @@ -78,11 +79,13 @@ pub fn init( ]) .state(move |state| { state.put::({ - create_http_client(user_agent.clone(), ca_data.clone()).unwrap() + create_http_client(user_agent.clone(), ca_data.clone(), proxy.clone()) + .unwrap() }); state.put::(HttpClientDefaults { ca_data: ca_data.clone(), user_agent: user_agent.clone(), + proxy: proxy.clone(), }); Ok(()) }) @@ -92,6 +95,7 @@ pub fn init( pub struct HttpClientDefaults { pub user_agent: String, pub ca_data: Option>, + pub proxy: Option, } pub trait FetchPermissions { @@ -461,6 +465,22 @@ impl HttpClientResource { pub struct CreateHttpClientOptions { ca_file: Option, ca_data: Option, + proxy: Option, +} + +#[derive(Deserialize, Default, Debug, Clone)] +#[serde(rename_all = "camelCase")] +#[serde(default)] +pub struct Proxy { + pub url: String, + pub basic_auth: Option, +} + +#[derive(Deserialize, Default, Debug, Clone)] +#[serde(default)] +pub struct BasicAuth { + pub username: String, + pub password: String, } pub fn op_create_http_client( @@ -476,6 +496,12 @@ where permissions.check_read(&PathBuf::from(ca_file))?; } + if let Some(proxy) = args.proxy.clone() { + let permissions = state.borrow_mut::(); + let url = Url::parse(&proxy.url)?; + permissions.check_net_url(&url)?; + } + let defaults = state.borrow::(); let cert_data = @@ -483,6 +509,7 @@ where let client = create_http_client( defaults.user_agent.clone(), cert_data.or_else(|| defaults.ca_data.clone()), + args.proxy, ) .unwrap(); @@ -510,6 +537,7 @@ fn get_cert_data( pub fn create_http_client( user_agent: String, ca_data: Option>, + proxy: Option, ) -> Result { let mut headers = HeaderMap::new(); headers.insert(USER_AGENT, user_agent.parse().unwrap()); @@ -523,6 +551,15 @@ pub fn create_http_client( builder = builder.add_root_certificate(cert); } + if let Some(proxy) = proxy { + let mut reqwest_proxy = reqwest::Proxy::all(&proxy.url)?; + if let Some(basic_auth) = &proxy.basic_auth { + reqwest_proxy = + reqwest_proxy.basic_auth(&basic_auth.username, &basic_auth.password); + } + builder = builder.proxy(reqwest_proxy); + } + builder .build() .map_err(|e| generic_error(format!("Unable to build http client: {}", e))) -- cgit v1.2.3