From be0a8fc27a8a79fbad28271720ca0b70dd535a95 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Mon, 9 Jun 2025 14:29:12 -0700 Subject: [PATCH] Add proxy bypass setting and rewrite proxy logic --- src-tauri/src/http_request.rs | 48 ++++++++++++------- src-tauri/yaak-models/bindings/gen_models.ts | 2 +- src-tauri/yaak-models/src/models.rs | 9 ++-- src-web/components/Settings/SettingsProxy.tsx | 41 ++++++++++++++-- 4 files changed, 74 insertions(+), 26 deletions(-) diff --git a/src-tauri/src/http_request.rs b/src-tauri/src/http_request.rs index 97597d59..a43ba29d 100644 --- a/src-tauri/src/http_request.rs +++ b/src-tauri/src/http_request.rs @@ -7,7 +7,7 @@ use http::{HeaderMap, HeaderName, HeaderValue}; use log::{debug, error, warn}; use mime_guess::Mime; use reqwest::redirect::Policy; -use reqwest::{Method, Response}; +use reqwest::{Method, NoProxy, Response}; use reqwest::{Proxy, Url, multipart}; use serde_json::Value; use std::collections::BTreeMap; @@ -120,25 +120,39 @@ pub async fn send_http_request( https, auth, disabled, + bypass, }) if !disabled => { - debug!("Using proxy http={http} https={https}"); - let mut proxy = Proxy::custom(move |url| { - let http = if http.is_empty() { None } else { Some(http.to_owned()) }; - let https = if https.is_empty() { None } else { Some(https.to_owned()) }; - let proxy_url = match (url.scheme(), http, https) { - ("http", Some(proxy_url), _) => Some(proxy_url), - ("https", _, Some(proxy_url)) => Some(proxy_url), - _ => None, + debug!("Using proxy http={http} https={https} bypass={bypass}"); + if !http.is_empty() { + match Proxy::http(http) { + Ok(mut proxy) => { + if let Some(ProxySettingAuth { user, password }) = auth.clone() { + debug!("Using http proxy auth"); + proxy = proxy.basic_auth(user.as_str(), password.as_str()); + } + proxy = proxy.no_proxy(NoProxy::from_string(&bypass)); + client_builder = client_builder.proxy(proxy); + } + Err(e) => { + warn!("Failed to apply http proxy {e:?}"); + } + }; + } + if !https.is_empty() { + match Proxy::https(https) { + Ok(mut proxy) => { + if let Some(ProxySettingAuth { user, password }) = auth { + debug!("Using https proxy auth"); + proxy = proxy.basic_auth(user.as_str(), password.as_str()); + } + proxy = proxy.no_proxy(NoProxy::from_string(&bypass)); + client_builder = client_builder.proxy(proxy); + } + Err(e) => { + warn!("Failed to apply https proxy {e:?}"); + } }; - proxy_url - }); - - if let Some(ProxySettingAuth { user, password }) = auth { - debug!("Using proxy auth"); - proxy = proxy.basic_auth(user.as_str(), password.as_str()); } - - client_builder = client_builder.proxy(proxy); } _ => {} // Nothing to do for this one, as it is the default } diff --git a/src-tauri/yaak-models/bindings/gen_models.ts b/src-tauri/yaak-models/bindings/gen_models.ts index 9e6c95cf..7da8e425 100644 --- a/src-tauri/yaak-models/bindings/gen_models.ts +++ b/src-tauri/yaak-models/bindings/gen_models.ts @@ -58,7 +58,7 @@ export type Plugin = { model: "plugin", id: string, createdAt: string, updatedAt export type PluginKeyValue = { model: "plugin_key_value", createdAt: string, updatedAt: string, pluginName: string, key: string, value: string, }; -export type ProxySetting = { "type": "enabled", disabled: boolean, http: string, https: string, auth: ProxySettingAuth | null, } | { "type": "disabled" }; +export type ProxySetting = { "type": "enabled", disabled: boolean, http: string, https: string, auth: ProxySettingAuth | null, bypass: string, } | { "type": "disabled" }; export type ProxySettingAuth = { user: string, password: string, }; diff --git a/src-tauri/yaak-models/src/models.rs b/src-tauri/yaak-models/src/models.rs index 2750f568..4581646e 100644 --- a/src-tauri/yaak-models/src/models.rs +++ b/src-tauri/yaak-models/src/models.rs @@ -31,12 +31,15 @@ macro_rules! impl_model { #[ts(export, export_to = "gen_models.ts")] pub enum ProxySetting { Enabled { - #[serde(default)] - // This was added after on so give it a default to be able to deserialize older values - disabled: bool, http: String, https: String, auth: Option, + + // These were added later, so give them defaults + #[serde(default)] + bypass: String, + #[serde(default)] + disabled: bool, }, Disabled, } diff --git a/src-web/components/Settings/SettingsProxy.tsx b/src-web/components/Settings/SettingsProxy.tsx index c2094f40..a315831d 100644 --- a/src-web/components/Settings/SettingsProxy.tsx +++ b/src-web/components/Settings/SettingsProxy.tsx @@ -30,6 +30,7 @@ export function SettingsProxy() { http: '', https: '', auth: { user: '', password: '' }, + bypass: '', }, }); } else { @@ -53,10 +54,11 @@ export function SettingsProxy() { const { proxy } = settings; const http = proxy?.type === 'enabled' ? proxy.http : ''; const https = proxy?.type === 'enabled' ? proxy.https : ''; + const bypass = proxy?.type === 'enabled' ? proxy.bypass : ''; const auth = proxy?.type === 'enabled' ? proxy.auth : null; const disabled = !enabled; await patchModel(settings, { - proxy: { type: 'enabled', http, https, auth, disabled }, + proxy: { type: 'enabled', http, https, auth, disabled, bypass }, }); }} /> @@ -73,6 +75,7 @@ export function SettingsProxy() { onChange={async (http) => { const { proxy } = settings; const https = proxy?.type === 'enabled' ? proxy.https : ''; + const bypass = proxy?.type === 'enabled' ? proxy.bypass : ''; const auth = proxy?.type === 'enabled' ? proxy.auth : null; const disabled = proxy?.type === 'enabled' ? proxy.disabled : false; await patchModel(settings, { @@ -82,6 +85,7 @@ export function SettingsProxy() { https, auth, disabled, + bypass, }, }); }} @@ -98,10 +102,11 @@ export function SettingsProxy() { onChange={async (https) => { const { proxy } = settings; const http = proxy?.type === 'enabled' ? proxy.http : ''; + const bypass = proxy?.type === 'enabled' ? proxy.bypass : ''; const auth = proxy?.type === 'enabled' ? proxy.auth : null; const disabled = proxy?.type === 'enabled' ? proxy.disabled : false; await patchModel(settings, { - proxy: { type: 'enabled', http, https, auth, disabled }, + proxy: { type: 'enabled', http, https, auth, disabled, bypass }, }); }} /> @@ -115,9 +120,10 @@ export function SettingsProxy() { const http = proxy?.type === 'enabled' ? proxy.http : ''; const https = proxy?.type === 'enabled' ? proxy.https : ''; const disabled = proxy?.type === 'enabled' ? proxy.disabled : false; + const bypass = proxy?.type === 'enabled' ? proxy.bypass : ''; const auth = enabled ? { user: '', password: '' } : null; await patchModel(settings, { - proxy: { type: 'enabled', http, https, auth, disabled }, + proxy: { type: 'enabled', http, https, auth, disabled, bypass }, }); }} /> @@ -135,10 +141,11 @@ export function SettingsProxy() { const http = proxy?.type === 'enabled' ? proxy.http : ''; const https = proxy?.type === 'enabled' ? proxy.https : ''; const disabled = proxy?.type === 'enabled' ? proxy.disabled : false; + const bypass = proxy?.type === 'enabled' ? proxy.bypass : ''; const password = proxy?.type === 'enabled' ? (proxy.auth?.password ?? '') : ''; const auth = { user, password }; await patchModel(settings, { - proxy: { type: 'enabled', http, https, auth, disabled }, + proxy: { type: 'enabled', http, https, auth, disabled, bypass }, }); }} /> @@ -153,15 +160,39 @@ export function SettingsProxy() { const http = proxy?.type === 'enabled' ? proxy.http : ''; const https = proxy?.type === 'enabled' ? proxy.https : ''; const disabled = proxy?.type === 'enabled' ? proxy.disabled : false; + const bypass = proxy?.type === 'enabled' ? proxy.bypass : ''; const user = proxy?.type === 'enabled' ? (proxy.auth?.user ?? '') : ''; const auth = { user, password }; await patchModel(settings, { - proxy: { type: 'enabled', http, https, auth, disabled }, + proxy: { type: 'enabled', http, https, auth, disabled, bypass }, }); }} /> )} + {settings.proxy.type === 'enabled' && ( + <> + + { + const { proxy } = settings; + const http = proxy?.type === 'enabled' ? proxy.http : ''; + const https = proxy?.type === 'enabled' ? proxy.https : ''; + const disabled = proxy?.type === 'enabled' ? proxy.disabled : false; + const user = proxy?.type === 'enabled' ? (proxy.auth?.user ?? '') : ''; + const password = proxy?.type === 'enabled' ? (proxy.auth?.password ?? '') : ''; + const auth = { user, password }; + await patchModel(settings, { + proxy: { type: 'enabled', http, https, auth, disabled, bypass }, + }); + }} + /> + + )} )}