Files
openidea/crates/ide-http/src/lib.rs
T
l0ng-aiandClaude 9d4e778c7b feat(settings): HTTP Proxy settings for the IDE's outgoing connections (#194)
* feat(settings): HTTP Proxy settings for the IDE's outgoing connections

Add Appearance & Behavior › System Settings › HTTP Proxy with three modes:
No proxy, Auto-detect proxy settings (the default; environment proxy as
before) and Manual proxy configuration (HTTP or SOCKS, host and port, a
comma-separated "No proxy for" list with `*` wildcards, optional proxy
authentication). "Check connection…" GETs a URL with the settings as edited
and reports the status or the error.

- ide-core: `ProxySettings` plus routing (no-proxy globs, loopback always
  direct, credentials percent-encoded), the current proxy for the process,
  curl arguments and child-process variables.
- ide-http: `client::build` / `client::shared` is the one HTTP client
  constructor; the HTTP Client requests and the update check go through it.
- ide-tools: curl downloads (tools, JDKs, debug adapters, agent registry,
  remote server) follow the setting.
- A manual proxy reaches child processes (language servers, debug adapters,
  terminals, git) as HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY.
- The proxy password is kept in the owner-only saved passwords file
  (`proxy-password.json` in the app data directory), not in settings.toml.

Co-Authored-By: Claude <[email protected]>

* fix(host): Allow the Unix-only post-start test helpers on Windows

Co-Authored-By: Claude <[email protected]>

---------

Co-authored-by: Claude <[email protected]>
2026-10-29 10:43:30 +08:00

77 lines
2.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! HTTP Client: IntelliJ-style `.http` request files.
//!
//! [`parse`] splits a file into requests, [`env`] resolves `{{variables}}` from
//! `http-client(.private).env.json`, [`exec`] sends a request (cancellable,
//! timed) and [`history`] keeps the responses. [`client`] builds every HTTP client
//! of the backend, with the proxy of System Settings › HTTP Proxy.
pub mod client;
pub mod env;
pub mod exec;
pub mod history;
pub mod parse;
pub use env::Environments;
pub use exec::{HttpResponse, PreparedRequest};
pub use history::{History, HistoryEntry, HttpExchange};
pub use parse::HttpRequestBlock;
use ide_core::{CancellationToken, IdeError, IdeResult, IpcPath};
use std::path::Path;
/// Where a request comes from and how to resolve it.
pub struct RunInput<'a> {
pub text: &'a str,
pub index: u32,
/// The request file (`None` for an unsaved buffer).
pub file: Option<&'a Path>,
pub root: Option<&'a Path>,
pub env: Option<&'a str>,
}
/// Prepares and sends request `index` of `text`. Preparation errors (bad
/// variables, missing includes) fail; transport errors are part of the exchange.
pub async fn run(input: RunInput<'_>, cancel: &CancellationToken) -> IdeResult<HttpExchange> {
let parsed = parse::parse(input.text);
let raw = parsed
.requests
.get(input.index as usize)
.ok_or_else(|| IdeError::not_found(format!("no request #{}", input.index + 1)))?;
let envs = Environments::load(input.file, input.root)?;
let request = exec::prepare(raw, &parsed.variables, &envs, input.env, input.file.and_then(Path::parent))?;
let time_ms = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_secs_f64() * 1000.0)
.unwrap_or_default();
let result = exec::execute(&request, cancel).await;
if let Err(e) = &result
&& e.kind == ide_core::error::ErrorKind::Cancelled
{
return Err(e.clone());
}
let (response, error) = match result {
Ok(r) => (Some(r), None),
Err(e) => (None, Some(e.message)),
};
Ok(HttpExchange {
entry: HistoryEntry {
id: uuid::Uuid::new_v4().simple().to_string(),
time_ms,
name: request.name.clone(),
method: request.method.clone(),
url: request.url.clone(),
status: response.as_ref().map(|r| r.status),
total_ms: response.as_ref().map(|r| r.total_ms),
file: input.file.map(IpcPath::from),
error,
},
request,
response,
})
}
/// Environment names available to `file`.
pub fn environments(file: Option<&Path>, root: Option<&Path>) -> IdeResult<Vec<String>> {
Ok(Environments::load(file, root)?.names())
}