Skip to content

Commit

Permalink
feat(proxi): support proxy configuration (#283)
Browse files Browse the repository at this point in the history
Fixes: #223
  • Loading branch information
eryue0220 committed Jul 31, 2023
1 parent 963e616 commit 87facfe
Show file tree
Hide file tree
Showing 10 changed files with 237 additions and 6 deletions.
20 changes: 18 additions & 2 deletions crates/nassun/src/client.rs
Expand Up @@ -28,6 +28,12 @@ pub struct NassunOpts {
default_tag: Option<String>,
registries: HashMap<Option<String>, Url>,
memoize_metadata: bool,
#[cfg(not(target_arch = "wasm32"))]
proxy: bool,
#[cfg(not(target_arch = "wasm32"))]
proxy_url: Option<String>,
#[cfg(not(target_arch = "wasm32"))]
no_proxy_domain: Option<String>,
}

impl NassunOpts {
Expand Down Expand Up @@ -88,15 +94,25 @@ impl NassunOpts {
#[cfg(target_arch = "wasm32")]
let client_builder = OroClient::builder().registry(registry);
#[cfg(not(target_arch = "wasm32"))]
let mut client_builder = OroClient::builder().registry(registry);
let mut client_builder = OroClient::builder()
.registry(registry)
.set_proxy(self.proxy);
#[cfg(not(target_arch = "wasm32"))]
let cache = if let Some(cache) = self.cache {
client_builder = client_builder.cache(cache.clone());
Arc::new(Some(cache))
} else {
Arc::new(None)
};
let client = client_builder.build();
#[cfg(not(target_arch = "wasm32"))]
if let Some(url) = self.proxy_url {
client_builder = client_builder.set_proxy_url(url).unwrap();
}
#[cfg(not(target_arch = "wasm32"))]
if let Some(url) = self.no_proxy_domain {
client_builder = client_builder.set_no_proxy(url);
}
let client: OroClient = client_builder.build();
Nassun {
#[cfg(not(target_arch = "wasm32"))]
cache,
Expand Down
80 changes: 76 additions & 4 deletions crates/oro-client/src/client.rs
Expand Up @@ -8,14 +8,25 @@ use reqwest::Client;
#[cfg(not(target_arch = "wasm32"))]
use reqwest::ClientBuilder;
#[cfg(not(target_arch = "wasm32"))]
use reqwest::{NoProxy, Proxy};
#[cfg(not(target_arch = "wasm32"))]
use reqwest_middleware::ClientWithMiddleware;
use url::Url;

#[cfg(not(target_arch = "wasm32"))]
use crate::OroClientError;

#[derive(Clone, Debug)]
pub struct OroClientBuilder {
registry: Url,
#[cfg(not(target_arch = "wasm32"))]
cache: Option<PathBuf>,
#[cfg(not(target_arch = "wasm32"))]
proxy: bool,
#[cfg(not(target_arch = "wasm32"))]
proxy_url: Option<Proxy>,
#[cfg(not(target_arch = "wasm32"))]
no_proxy_domain: Option<String>,
}

impl Default for OroClientBuilder {
Expand All @@ -24,6 +35,12 @@ impl Default for OroClientBuilder {
registry: Url::parse("https://registry.npmjs.org").unwrap(),
#[cfg(not(target_arch = "wasm32"))]
cache: None,
#[cfg(not(target_arch = "wasm32"))]
proxy: false,
#[cfg(not(target_arch = "wasm32"))]
proxy_url: None,
#[cfg(not(target_arch = "wasm32"))]
no_proxy_domain: None,
}
}
}
Expand All @@ -44,17 +61,61 @@ impl OroClientBuilder {
self
}

#[cfg(not(target_arch = "wasm32"))]
pub fn set_proxy(mut self, proxy: bool) -> Self {
self.proxy = proxy;
self
}

#[cfg(not(target_arch = "wasm32"))]
pub fn set_proxy_url(mut self, proxy_url: impl AsRef<str>) -> Result<Self, OroClientError> {
match Url::parse(proxy_url.as_ref()) {
Ok(url_info) => {
let username = url_info.username();
let password = url_info.password();
let mut proxy = Proxy::all(url_info.as_ref())?;

if let Some(password_str) = password {
proxy = proxy.basic_auth(username, password_str);
}

proxy = proxy.no_proxy(self.get_no_proxy());
self.proxy_url = Some(proxy);
self.proxy = true;
Ok(self)
}
Err(e) => Err(OroClientError::UrlParseError(e)),
}
}

#[cfg(not(target_arch = "wasm32"))]
pub fn set_no_proxy(mut self, no_proxy_domain: impl AsRef<str>) -> Self {
self.no_proxy_domain = Some(no_proxy_domain.as_ref().into());
self
}

pub fn build(self) -> OroClient {
#[cfg(target_arch = "wasm32")]
let client_uncached = Client::new();

#[cfg(not(target_arch = "wasm32"))]
let client_uncached = ClientBuilder::new()
let mut client_core = ClientBuilder::new()
.user_agent("orogene")
.pool_max_idle_per_host(20)
.timeout(std::time::Duration::from_secs(60 * 5))
.build()
.expect("Failed to build HTTP client.");
.timeout(std::time::Duration::from_secs(60 * 5));

#[cfg(not(target_arch = "wasm32"))]
if let Some(url) = self.proxy_url {
client_core = client_core.proxy(url);
}

#[cfg(not(target_arch = "wasm32"))]
if !self.proxy {
client_core = client_core.no_proxy();
}

#[cfg(not(target_arch = "wasm32"))]
let client_uncached = client_core.build().expect("Fail to build HTTP client.");

#[cfg(not(target_arch = "wasm32"))]
let mut client_builder = reqwest_middleware::ClientBuilder::new(client_uncached.clone());
Expand All @@ -80,6 +141,17 @@ impl OroClientBuilder {
client_uncached,
}
}

#[cfg(not(target_arch = "wasm32"))]
fn get_no_proxy(&self) -> Option<NoProxy> {
if let Some(ref no_proxy_conf) = self.no_proxy_domain {
if !no_proxy_conf.is_empty() {
return NoProxy::from_string(no_proxy_conf);
}
}

NoProxy::from_env().or(None)
}
}

#[derive(Clone, Debug)]
Expand Down
9 changes: 9 additions & 0 deletions src/apply_args.rs
Expand Up @@ -104,6 +104,15 @@ pub struct ApplyArgs {

#[arg(from_global)]
pub emoji: bool,

#[arg(from_global)]
pub proxy: bool,

#[arg(from_global)]
pub proxy_url: Option<String>,

#[arg(from_global)]
pub no_proxy: Option<String>,
}

impl ApplyArgs {
Expand Down
32 changes: 32 additions & 0 deletions src/lib.rs
Expand Up @@ -256,6 +256,38 @@ pub struct Orogene {

#[command(subcommand)]
subcommand: OroCmd,

/// Use proxy to delegate the network.
///
/// Proxy is opt-in, it uses for outgoing http/https request.
/// If enabled, should set proxy-url too.
#[arg(
help_heading = "Global Options",
global = true,
long,
default_value_t = false
)]
proxy: bool,

/// A proxy to use for outgoing http requests.
#[arg(
help_heading = "Global Options",
global = true,
long = "proxy-url",
default_value = None
)]
proxy_url: Option<String>,

/// Use commas to separate multiple entries, e.g. `.host1.com,.host2.com`.
///
/// Can also be configured through the `NO_PROXY` environment variable, like `NO_PROXY=.host1.com`.
#[arg(
help_heading = "Global Options",
global = true,
long = "no-proxy-domain",
default_value = None
)]
no_proxy_domain: Option<String>,
}

impl Orogene {
Expand Down
17 changes: 17 additions & 0 deletions tests/snapshots/help__add.snap
@@ -1,5 +1,6 @@
---
source: tests/help.rs
assertion_line: 7
expression: "sub_md(\"add\")"
---
stderr:
Expand Down Expand Up @@ -191,4 +192,20 @@ Telemetry for Orogene is opt-in, anonymous, and is used to help the team improve
Sentry DSN (access token) where telemetry will be sent (if enabled)
#### `--proxy`
Use proxy to delegate the network.
Proxy is opt-in, it uses for outgoing http/https request. If enabled, should set proxy-url too.
#### `--proxy-url <PROXY_URL>`
A proxy to use for outgoing http requests
#### `--no-proxy-domain <NO_PROXY_DOMAIN>`
Use commas to separate multiple entries, e.g. `.host1.com,.host2.com`.
Can also be configured through the `NO_PROXY` environment variable, like `NO_PROXY=.host1.com`.
17 changes: 17 additions & 0 deletions tests/snapshots/help__apply.snap
@@ -1,5 +1,6 @@
---
source: tests/help.rs
assertion_line: 12
expression: "sub_md(\"apply\")"
---
stderr:
Expand Down Expand Up @@ -171,4 +172,20 @@ Telemetry for Orogene is opt-in, anonymous, and is used to help the team improve
Sentry DSN (access token) where telemetry will be sent (if enabled)
#### `--proxy`
Use proxy to delegate the network.
Proxy is opt-in, it uses for outgoing http/https request. If enabled, should set proxy-url too.
#### `--proxy-url <PROXY_URL>`
A proxy to use for outgoing http requests
#### `--no-proxy-domain <NO_PROXY_DOMAIN>`
Use commas to separate multiple entries, e.g. `.host1.com,.host2.com`.
Can also be configured through the `NO_PROXY` environment variable, like `NO_PROXY=.host1.com`.
17 changes: 17 additions & 0 deletions tests/snapshots/help__ping.snap
@@ -1,5 +1,6 @@
---
source: tests/help.rs
assertion_line: 17
expression: "sub_md(\"ping\")"
---
stderr:
Expand Down Expand Up @@ -105,4 +106,20 @@ Telemetry for Orogene is opt-in, anonymous, and is used to help the team improve
Sentry DSN (access token) where telemetry will be sent (if enabled)
#### `--proxy`
Use proxy to delegate the network.
Proxy is opt-in, it uses for outgoing http/https request. If enabled, should set proxy-url too.
#### `--proxy-url <PROXY_URL>`
A proxy to use for outgoing http requests
#### `--no-proxy-domain <NO_PROXY_DOMAIN>`
Use commas to separate multiple entries, e.g. `.host1.com,.host2.com`.
Can also be configured through the `NO_PROXY` environment variable, like `NO_PROXY=.host1.com`.
17 changes: 17 additions & 0 deletions tests/snapshots/help__reapply.snap
@@ -1,5 +1,6 @@
---
source: tests/help.rs
assertion_line: 22
expression: "sub_md(\"reapply\")"
---
stderr:
Expand Down Expand Up @@ -167,4 +168,20 @@ Telemetry for Orogene is opt-in, anonymous, and is used to help the team improve
Sentry DSN (access token) where telemetry will be sent (if enabled)
#### `--proxy`
Use proxy to delegate the network.
Proxy is opt-in, it uses for outgoing http/https request. If enabled, should set proxy-url too.
#### `--proxy-url <PROXY_URL>`
A proxy to use for outgoing http requests
#### `--no-proxy-domain <NO_PROXY_DOMAIN>`
Use commas to separate multiple entries, e.g. `.host1.com,.host2.com`.
Can also be configured through the `NO_PROXY` environment variable, like `NO_PROXY=.host1.com`.
17 changes: 17 additions & 0 deletions tests/snapshots/help__remove.snap
@@ -1,5 +1,6 @@
---
source: tests/help.rs
assertion_line: 27
expression: "sub_md(\"remove\")"
---
stderr:
Expand Down Expand Up @@ -175,4 +176,20 @@ Telemetry for Orogene is opt-in, anonymous, and is used to help the team improve
Sentry DSN (access token) where telemetry will be sent (if enabled)
#### `--proxy`
Use proxy to delegate the network.
Proxy is opt-in, it uses for outgoing http/https request. If enabled, should set proxy-url too.
#### `--proxy-url <PROXY_URL>`
A proxy to use for outgoing http requests
#### `--no-proxy-domain <NO_PROXY_DOMAIN>`
Use commas to separate multiple entries, e.g. `.host1.com,.host2.com`.
Can also be configured through the `NO_PROXY` environment variable, like `NO_PROXY=.host1.com`.
17 changes: 17 additions & 0 deletions tests/snapshots/help__view.snap
@@ -1,5 +1,6 @@
---
source: tests/help.rs
assertion_line: 32
expression: "sub_md(\"view\")"
---
stderr:
Expand Down Expand Up @@ -119,4 +120,20 @@ Telemetry for Orogene is opt-in, anonymous, and is used to help the team improve
Sentry DSN (access token) where telemetry will be sent (if enabled)
#### `--proxy`
Use proxy to delegate the network.
Proxy is opt-in, it uses for outgoing http/https request. If enabled, should set proxy-url too.
#### `--proxy-url <PROXY_URL>`
A proxy to use for outgoing http requests
#### `--no-proxy-domain <NO_PROXY_DOMAIN>`
Use commas to separate multiple entries, e.g. `.host1.com,.host2.com`.
Can also be configured through the `NO_PROXY` environment variable, like `NO_PROXY=.host1.com`.

0 comments on commit 87facfe

Please sign in to comment.