mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-23 17:28:29 +02:00
Add proxy bypass setting and rewrite proxy logic
This commit is contained in:
@@ -7,7 +7,7 @@ use http::{HeaderMap, HeaderName, HeaderValue};
|
|||||||
use log::{debug, error, warn};
|
use log::{debug, error, warn};
|
||||||
use mime_guess::Mime;
|
use mime_guess::Mime;
|
||||||
use reqwest::redirect::Policy;
|
use reqwest::redirect::Policy;
|
||||||
use reqwest::{Method, Response};
|
use reqwest::{Method, NoProxy, Response};
|
||||||
use reqwest::{Proxy, Url, multipart};
|
use reqwest::{Proxy, Url, multipart};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
@@ -120,25 +120,39 @@ pub async fn send_http_request<R: Runtime>(
|
|||||||
https,
|
https,
|
||||||
auth,
|
auth,
|
||||||
disabled,
|
disabled,
|
||||||
|
bypass,
|
||||||
}) if !disabled => {
|
}) if !disabled => {
|
||||||
debug!("Using proxy http={http} https={https}");
|
debug!("Using proxy http={http} https={https} bypass={bypass}");
|
||||||
let mut proxy = Proxy::custom(move |url| {
|
if !http.is_empty() {
|
||||||
let http = if http.is_empty() { None } else { Some(http.to_owned()) };
|
match Proxy::http(http) {
|
||||||
let https = if https.is_empty() { None } else { Some(https.to_owned()) };
|
Ok(mut proxy) => {
|
||||||
let proxy_url = match (url.scheme(), http, https) {
|
if let Some(ProxySettingAuth { user, password }) = auth.clone() {
|
||||||
("http", Some(proxy_url), _) => Some(proxy_url),
|
debug!("Using http proxy auth");
|
||||||
("https", _, Some(proxy_url)) => Some(proxy_url),
|
proxy = proxy.basic_auth(user.as_str(), password.as_str());
|
||||||
_ => None,
|
}
|
||||||
|
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
|
_ => {} // Nothing to do for this one, as it is the default
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 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, };
|
export type ProxySettingAuth = { user: string, password: string, };
|
||||||
|
|
||||||
|
|||||||
@@ -31,12 +31,15 @@ macro_rules! impl_model {
|
|||||||
#[ts(export, export_to = "gen_models.ts")]
|
#[ts(export, export_to = "gen_models.ts")]
|
||||||
pub enum ProxySetting {
|
pub enum ProxySetting {
|
||||||
Enabled {
|
Enabled {
|
||||||
#[serde(default)]
|
|
||||||
// This was added after on so give it a default to be able to deserialize older values
|
|
||||||
disabled: bool,
|
|
||||||
http: String,
|
http: String,
|
||||||
https: String,
|
https: String,
|
||||||
auth: Option<ProxySettingAuth>,
|
auth: Option<ProxySettingAuth>,
|
||||||
|
|
||||||
|
// These were added later, so give them defaults
|
||||||
|
#[serde(default)]
|
||||||
|
bypass: String,
|
||||||
|
#[serde(default)]
|
||||||
|
disabled: bool,
|
||||||
},
|
},
|
||||||
Disabled,
|
Disabled,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export function SettingsProxy() {
|
|||||||
http: '',
|
http: '',
|
||||||
https: '',
|
https: '',
|
||||||
auth: { user: '', password: '' },
|
auth: { user: '', password: '' },
|
||||||
|
bypass: '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -53,10 +54,11 @@ export function SettingsProxy() {
|
|||||||
const { proxy } = settings;
|
const { proxy } = settings;
|
||||||
const http = proxy?.type === 'enabled' ? proxy.http : '';
|
const http = proxy?.type === 'enabled' ? proxy.http : '';
|
||||||
const https = proxy?.type === 'enabled' ? proxy.https : '';
|
const https = proxy?.type === 'enabled' ? proxy.https : '';
|
||||||
|
const bypass = proxy?.type === 'enabled' ? proxy.bypass : '';
|
||||||
const auth = proxy?.type === 'enabled' ? proxy.auth : null;
|
const auth = proxy?.type === 'enabled' ? proxy.auth : null;
|
||||||
const disabled = !enabled;
|
const disabled = !enabled;
|
||||||
await patchModel(settings, {
|
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) => {
|
onChange={async (http) => {
|
||||||
const { proxy } = settings;
|
const { proxy } = settings;
|
||||||
const https = proxy?.type === 'enabled' ? proxy.https : '';
|
const https = proxy?.type === 'enabled' ? proxy.https : '';
|
||||||
|
const bypass = proxy?.type === 'enabled' ? proxy.bypass : '';
|
||||||
const auth = proxy?.type === 'enabled' ? proxy.auth : null;
|
const auth = proxy?.type === 'enabled' ? proxy.auth : null;
|
||||||
const disabled = proxy?.type === 'enabled' ? proxy.disabled : false;
|
const disabled = proxy?.type === 'enabled' ? proxy.disabled : false;
|
||||||
await patchModel(settings, {
|
await patchModel(settings, {
|
||||||
@@ -82,6 +85,7 @@ export function SettingsProxy() {
|
|||||||
https,
|
https,
|
||||||
auth,
|
auth,
|
||||||
disabled,
|
disabled,
|
||||||
|
bypass,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -98,10 +102,11 @@ export function SettingsProxy() {
|
|||||||
onChange={async (https) => {
|
onChange={async (https) => {
|
||||||
const { proxy } = settings;
|
const { proxy } = settings;
|
||||||
const http = proxy?.type === 'enabled' ? proxy.http : '';
|
const http = proxy?.type === 'enabled' ? proxy.http : '';
|
||||||
|
const bypass = proxy?.type === 'enabled' ? proxy.bypass : '';
|
||||||
const auth = proxy?.type === 'enabled' ? proxy.auth : null;
|
const auth = proxy?.type === 'enabled' ? proxy.auth : null;
|
||||||
const disabled = proxy?.type === 'enabled' ? proxy.disabled : false;
|
const disabled = proxy?.type === 'enabled' ? proxy.disabled : false;
|
||||||
await patchModel(settings, {
|
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 http = proxy?.type === 'enabled' ? proxy.http : '';
|
||||||
const https = proxy?.type === 'enabled' ? proxy.https : '';
|
const https = proxy?.type === 'enabled' ? proxy.https : '';
|
||||||
const disabled = proxy?.type === 'enabled' ? proxy.disabled : false;
|
const disabled = proxy?.type === 'enabled' ? proxy.disabled : false;
|
||||||
|
const bypass = proxy?.type === 'enabled' ? proxy.bypass : '';
|
||||||
const auth = enabled ? { user: '', password: '' } : null;
|
const auth = enabled ? { user: '', password: '' } : null;
|
||||||
await patchModel(settings, {
|
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 http = proxy?.type === 'enabled' ? proxy.http : '';
|
||||||
const https = proxy?.type === 'enabled' ? proxy.https : '';
|
const https = proxy?.type === 'enabled' ? proxy.https : '';
|
||||||
const disabled = proxy?.type === 'enabled' ? proxy.disabled : false;
|
const disabled = proxy?.type === 'enabled' ? proxy.disabled : false;
|
||||||
|
const bypass = proxy?.type === 'enabled' ? proxy.bypass : '';
|
||||||
const password = proxy?.type === 'enabled' ? (proxy.auth?.password ?? '') : '';
|
const password = proxy?.type === 'enabled' ? (proxy.auth?.password ?? '') : '';
|
||||||
const auth = { user, password };
|
const auth = { user, password };
|
||||||
await patchModel(settings, {
|
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 http = proxy?.type === 'enabled' ? proxy.http : '';
|
||||||
const https = proxy?.type === 'enabled' ? proxy.https : '';
|
const https = proxy?.type === 'enabled' ? proxy.https : '';
|
||||||
const disabled = proxy?.type === 'enabled' ? proxy.disabled : false;
|
const disabled = proxy?.type === 'enabled' ? proxy.disabled : false;
|
||||||
|
const bypass = proxy?.type === 'enabled' ? proxy.bypass : '';
|
||||||
const user = proxy?.type === 'enabled' ? (proxy.auth?.user ?? '') : '';
|
const user = proxy?.type === 'enabled' ? (proxy.auth?.user ?? '') : '';
|
||||||
const auth = { user, password };
|
const auth = { user, password };
|
||||||
await patchModel(settings, {
|
await patchModel(settings, {
|
||||||
proxy: { type: 'enabled', http, https, auth, disabled },
|
proxy: { type: 'enabled', http, https, auth, disabled, bypass },
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</HStack>
|
</HStack>
|
||||||
)}
|
)}
|
||||||
|
{settings.proxy.type === 'enabled' && (
|
||||||
|
<>
|
||||||
|
<Separator className="my-6" />
|
||||||
|
<PlainInput
|
||||||
|
label="Proxy Bypass"
|
||||||
|
help="Comma-separated list to bypass the proxy."
|
||||||
|
defaultValue={settings.proxy.bypass}
|
||||||
|
placeholder="127.0.0.1, *.example.com, localhost:3000"
|
||||||
|
onChange={async (bypass) => {
|
||||||
|
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 },
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</VStack>
|
</VStack>
|
||||||
)}
|
)}
|
||||||
</VStack>
|
</VStack>
|
||||||
|
|||||||
Reference in New Issue
Block a user