mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
Add basic proxy settings (#11852)
Adding `proxy` keyword to configure proxy while using zed. After setting the proxy, restart Zed to acctually use the proxy. Example setting: ```rust "proxy" = "socks5://localhost:10808" "proxy" = "http://127.0.0.1:10809" ``` Closes #9424, closes #9422, closes #8650, closes #5032, closes #6701, closes #11890 Release Notes: - Added settings to configure proxy in Zed --------- Co-authored-by: Jason Lee <huacnlee@gmail.com>
This commit is contained in:
parent
90b631ff3e
commit
1b261608c6
@ -797,5 +797,17 @@
|
|||||||
// - `short`: "2 s, 15 l, 32 c"
|
// - `short`: "2 s, 15 l, 32 c"
|
||||||
// - `long`: "2 selections, 15 lines, 32 characters"
|
// - `long`: "2 selections, 15 lines, 32 characters"
|
||||||
// Default: long
|
// Default: long
|
||||||
"line_indicator_format": "long"
|
"line_indicator_format": "long",
|
||||||
}
|
// Set a proxy to use. The proxy protocol is specified by the URI scheme.
|
||||||
|
//
|
||||||
|
// Supported URI scheme: `http`, `https`, `socks4`, `socks4a`, `socks5`,
|
||||||
|
// `socks5h`. `http` will be used when no scheme is specified.
|
||||||
|
//
|
||||||
|
// By default no proxy will be used, or Zed will try get proxy settings from
|
||||||
|
// environment variables.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
// - "proxy" = "socks5://localhost:10808"
|
||||||
|
// - "proxy" = "http://127.0.0.1:10809"
|
||||||
|
"proxy": null
|
||||||
|
}
|
@ -114,10 +114,36 @@ impl Settings for ClientSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Serialize, Deserialize, JsonSchema)]
|
||||||
|
pub struct ProxySettingsContent {
|
||||||
|
proxy: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
pub struct ProxySettings {
|
||||||
|
pub proxy: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Settings for ProxySettings {
|
||||||
|
const KEY: Option<&'static str> = None;
|
||||||
|
|
||||||
|
type FileContent = ProxySettingsContent;
|
||||||
|
|
||||||
|
fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
proxy: sources
|
||||||
|
.user
|
||||||
|
.and_then(|value| value.proxy.clone())
|
||||||
|
.or(sources.default.proxy.clone()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init_settings(cx: &mut AppContext) {
|
pub fn init_settings(cx: &mut AppContext) {
|
||||||
TelemetrySettings::register(cx);
|
TelemetrySettings::register(cx);
|
||||||
cx.update_global(|store: &mut SettingsStore, cx| {
|
cx.update_global(|store: &mut SettingsStore, cx| {
|
||||||
store.register_setting::<ClientSettings>(cx);
|
store.register_setting::<ClientSettings>(cx);
|
||||||
|
store.register_setting::<ProxySettings>(cx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,6 +538,7 @@ impl Client {
|
|||||||
let clock = Arc::new(clock::RealSystemClock);
|
let clock = Arc::new(clock::RealSystemClock);
|
||||||
let http = Arc::new(HttpClientWithUrl::new(
|
let http = Arc::new(HttpClientWithUrl::new(
|
||||||
&ClientSettings::get_global(cx).server_url,
|
&ClientSettings::get_global(cx).server_url,
|
||||||
|
ProxySettings::get_global(cx).proxy.clone(),
|
||||||
));
|
));
|
||||||
Self::new(clock, http.clone(), cx)
|
Self::new(clock, http.clone(), cx)
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ impl ExtensionBuilder {
|
|||||||
pub fn new(cache_dir: PathBuf) -> Self {
|
pub fn new(cache_dir: PathBuf) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cache_dir,
|
cache_dir,
|
||||||
http: http::client(),
|
http: http::client(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ impl App {
|
|||||||
Self(AppContext::new(
|
Self(AppContext::new(
|
||||||
current_platform(),
|
current_platform(),
|
||||||
Arc::new(()),
|
Arc::new(()),
|
||||||
http::client(),
|
http::client(None),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,6 +651,11 @@ impl AppContext {
|
|||||||
self.platform.local_timezone()
|
self.platform.local_timezone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates the http client assigned to GPUI
|
||||||
|
pub fn update_http_client(&mut self, new_client: Arc<dyn HttpClient>) {
|
||||||
|
self.http_client = new_client;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the http client assigned to GPUI
|
/// Returns the http client assigned to GPUI
|
||||||
pub fn http_client(&self) -> Arc<dyn HttpClient> {
|
pub fn http_client(&self) -> Arc<dyn HttpClient> {
|
||||||
self.http_client.clone()
|
self.http_client.clone()
|
||||||
|
@ -16,7 +16,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
pub use url::Url;
|
pub use url::Url;
|
||||||
|
|
||||||
fn http_proxy_from_env() -> Option<isahc::http::Uri> {
|
fn get_proxy(proxy: Option<String>) -> Option<isahc::http::Uri> {
|
||||||
macro_rules! try_env {
|
macro_rules! try_env {
|
||||||
($($env:literal),+) => {
|
($($env:literal),+) => {
|
||||||
$(
|
$(
|
||||||
@ -27,29 +27,42 @@ fn http_proxy_from_env() -> Option<isahc::http::Uri> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
try_env!(
|
proxy
|
||||||
"ALL_PROXY",
|
.and_then(|input| {
|
||||||
"all_proxy",
|
input
|
||||||
"HTTPS_PROXY",
|
.parse::<isahc::http::Uri>()
|
||||||
"https_proxy",
|
.inspect_err(|e| log::error!("Error parsing proxy settings: {}", e))
|
||||||
"HTTP_PROXY",
|
.ok()
|
||||||
"http_proxy"
|
})
|
||||||
);
|
.or_else(|| {
|
||||||
None
|
try_env!(
|
||||||
|
"ALL_PROXY",
|
||||||
|
"all_proxy",
|
||||||
|
"HTTPS_PROXY",
|
||||||
|
"https_proxy",
|
||||||
|
"HTTP_PROXY",
|
||||||
|
"http_proxy"
|
||||||
|
);
|
||||||
|
None
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An [`HttpClient`] that has a base URL.
|
/// An [`HttpClient`] that has a base URL.
|
||||||
pub struct HttpClientWithUrl {
|
pub struct HttpClientWithUrl {
|
||||||
base_url: Mutex<String>,
|
base_url: Mutex<String>,
|
||||||
client: Arc<dyn HttpClient>,
|
client: Arc<dyn HttpClient>,
|
||||||
|
proxy: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HttpClientWithUrl {
|
impl HttpClientWithUrl {
|
||||||
/// Returns a new [`HttpClientWithUrl`] with the given base URL.
|
/// Returns a new [`HttpClientWithUrl`] with the given base URL.
|
||||||
pub fn new(base_url: impl Into<String>) -> Self {
|
pub fn new(base_url: impl Into<String>, unparsed_proxy: Option<String>) -> Self {
|
||||||
|
let parsed_proxy = get_proxy(unparsed_proxy);
|
||||||
|
let proxy_string = parsed_proxy.as_ref().map(|p| p.to_string());
|
||||||
Self {
|
Self {
|
||||||
base_url: Mutex::new(base_url.into()),
|
base_url: Mutex::new(base_url.into()),
|
||||||
client: client(),
|
client: client(parsed_proxy),
|
||||||
|
proxy: proxy_string,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +113,10 @@ impl HttpClient for Arc<HttpClientWithUrl> {
|
|||||||
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
|
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
|
||||||
self.client.send(req)
|
self.client.send(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn proxy(&self) -> Option<&str> {
|
||||||
|
self.proxy.as_deref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HttpClient for HttpClientWithUrl {
|
impl HttpClient for HttpClientWithUrl {
|
||||||
@ -109,6 +126,10 @@ impl HttpClient for HttpClientWithUrl {
|
|||||||
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
|
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
|
||||||
self.client.send(req)
|
self.client.send(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn proxy(&self) -> Option<&str> {
|
||||||
|
self.proxy.as_deref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait HttpClient: Send + Sync {
|
pub trait HttpClient: Send + Sync {
|
||||||
@ -153,14 +174,16 @@ pub trait HttpClient: Send + Sync {
|
|||||||
Err(error) => async move { Err(error.into()) }.boxed(),
|
Err(error) => async move { Err(error.into()) }.boxed(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn proxy(&self) -> Option<&str>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn client() -> Arc<dyn HttpClient> {
|
pub fn client(proxy: Option<isahc::http::Uri>) -> Arc<dyn HttpClient> {
|
||||||
Arc::new(
|
Arc::new(
|
||||||
isahc::HttpClient::builder()
|
isahc::HttpClient::builder()
|
||||||
.connect_timeout(Duration::from_secs(5))
|
.connect_timeout(Duration::from_secs(5))
|
||||||
.low_speed_timeout(100, Duration::from_secs(5))
|
.low_speed_timeout(100, Duration::from_secs(5))
|
||||||
.proxy(http_proxy_from_env())
|
.proxy(proxy)
|
||||||
.build()
|
.build()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
@ -174,6 +197,10 @@ impl HttpClient for isahc::HttpClient {
|
|||||||
let client = self.clone();
|
let client = self.clone();
|
||||||
Box::pin(async move { client.send_async(req).await })
|
Box::pin(async move { client.send_async(req).await })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn proxy(&self) -> Option<&str> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "test-support")]
|
#[cfg(feature = "test-support")]
|
||||||
@ -201,6 +228,7 @@ impl FakeHttpClient {
|
|||||||
client: Arc::new(Self {
|
client: Arc::new(Self {
|
||||||
handler: Box::new(move |req| Box::pin(handler(req))),
|
handler: Box::new(move |req| Box::pin(handler(req))),
|
||||||
}),
|
}),
|
||||||
|
proxy: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,4 +267,8 @@ impl HttpClient for FakeHttpClient {
|
|||||||
let future = (self.handler)(req);
|
let future = (self.handler)(req);
|
||||||
Box::pin(async move { future.await.map(Into::into) })
|
Box::pin(async move { future.await.map(Into::into) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn proxy(&self) -> Option<&str> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,8 +266,21 @@ impl NodeRuntime for RealNodeRuntime {
|
|||||||
command.args(["--prefix".into(), directory.to_path_buf()]);
|
command.args(["--prefix".into(), directory.to_path_buf()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(proxy) = self.http.proxy() {
|
||||||
|
command.args(["--proxy", proxy]);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
command.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
|
{
|
||||||
|
// SYSTEMROOT is a critical environment variables for Windows.
|
||||||
|
if let Some(val) = std::env::var("SYSTEMROOT")
|
||||||
|
.context("Missing environment variable: SYSTEMROOT!")
|
||||||
|
.log_err()
|
||||||
|
{
|
||||||
|
command.env("SYSTEMROOT", val);
|
||||||
|
}
|
||||||
|
command.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
|
||||||
|
}
|
||||||
|
|
||||||
command.output().await.map_err(|e| anyhow!("{e}"))
|
command.output().await.map_err(|e| anyhow!("{e}"))
|
||||||
};
|
};
|
||||||
|
@ -26,7 +26,7 @@ fn main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let clock = Arc::new(FakeSystemClock::default());
|
let clock = Arc::new(FakeSystemClock::default());
|
||||||
let http = Arc::new(HttpClientWithUrl::new("http://localhost:11434"));
|
let http = Arc::new(HttpClientWithUrl::new("http://localhost:11434", None));
|
||||||
|
|
||||||
let client = client::Client::new(clock, http.clone(), cx);
|
let client = client::Client::new(clock, http.clone(), cx);
|
||||||
Client::set_global(client.clone(), cx);
|
Client::set_global(client.clone(), cx);
|
||||||
|
@ -343,6 +343,7 @@ fn main() {
|
|||||||
|
|
||||||
client::init_settings(cx);
|
client::init_settings(cx);
|
||||||
let client = Client::production(cx);
|
let client = Client::production(cx);
|
||||||
|
cx.update_http_client(client.http_client().clone());
|
||||||
let mut languages =
|
let mut languages =
|
||||||
LanguageRegistry::new(login_shell_env_loaded, cx.background_executor().clone());
|
LanguageRegistry::new(login_shell_env_loaded, cx.background_executor().clone());
|
||||||
languages.set_language_server_download_dir(paths::LANGUAGES_DIR.clone());
|
languages.set_language_server_download_dir(paths::LANGUAGES_DIR.clone());
|
||||||
|
Loading…
Reference in New Issue
Block a user