Skip to content

Commit dddc260

Browse files
committed
feat: add explicit HTTP proxy support for AUR requests
Add Proxy and NoProxy configuration options for paru's HTTP requests to the AUR. This addresses issues where automatic proxy detection via environment variables (HTTP_PROXY/HTTPS_PROXY) fails with reqwest. Supported proxy schemes: http://, https://, socks5:// This only affects paru's direct HTTP requests (RPC queries, packages.gz, PKGBUILDs). Git clone/fetch operations and pacman downloads use their respective separate proxy configuration. Closes #1473 Signed-off-by: Josephine Pfeiffer <hi@josie.lol>
1 parent ef5bacd commit dddc260

8 files changed

Lines changed: 78 additions & 14 deletions

File tree

man/paru.8

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,17 @@ Set an alternative AUR URL.
302302
.B \-\-aurrpcurl
303303
Set an alternative URL for the AUR /rpc endpoint.
304304

305+
.TP
306+
.B \-\-proxy <url>
307+
Override proxy for paru's HTTP requests to the AUR. Supports http://,
308+
https://, and socks5:// schemes. Paru respects standard proxy environment
309+
variables by default; this option overrides them. Does not affect git or pacman.
310+
311+
.TP
312+
.B \-\-noproxy <hosts>
313+
Comma-separated list of hosts to bypass the proxy. Only applies when --proxy
314+
is set.
315+
305316
.TP
306317
.B \-\-clonedir <dir>
307318
Directory used to download and run PKGBUILDs.

man/paru.conf.5

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ paru.conf \- paru configuration file
88
$PARU_CONF, $XDG_CONFIG_HOME/paru/paru.conf, $HOME/.config/paru/paru.conf, /etc/paru.conf
99

1010
.SH DESCRIPTION
11-
Paru's config file. Based on the format used by
11+
Paru's config file. Based on the format used by
1212
.BR pacman.conf (5)
1313

1414
Paru first attempts to read the file at $PARU_CONF. If $PARU_CONF is not
@@ -178,7 +178,7 @@ during builds allowing an option to be chosen then.
178178
.TP
179179
.B UpgradeMenu
180180
Show a detailed list of updates in a similar format to pacman's VerbosePkgLists
181-
option. (See
181+
option. (See
182182
.BR pacman.conf(5)).
183183
Upgrades can be skipped using numbers, number ranges, or repo
184184
names.
@@ -196,6 +196,28 @@ Set an alternative AUR URL.
196196
.B AurRpcUrl = URL
197197
Set an alternative URL for the AUR /rpc endpoint.
198198

199+
.TP
200+
.B Proxy = URL
201+
Set an explicit proxy URL for paru's HTTP requests to the AUR (RPC queries,
202+
package lists, PKGBUILDs). Supports http://, https://, and socks5:// schemes.
203+
.sp
204+
Paru automatically respects the standard proxy environment variables
205+
(HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY). This option is only needed if
206+
you want to override the environment or use a different proxy specifically
207+
for AUR requests.
208+
.sp
209+
This does \fBnot\fR affect git operations (cloning/fetching AUR repos) or
210+
pacman downloads. Git and pacman also respect standard proxy environment
211+
variables. For git-specific configuration, use \fBgit config --global
212+
http.proxy\fR.
213+
214+
.TP
215+
.B NoProxy = hosts
216+
Comma-separated list of hosts to bypass the proxy. Only applies when Proxy is
217+
set. Supports IP addresses, CIDR notation (e.g., 192.168.1.0/24), domain names,
218+
and wildcards.
219+
Example: localhost,127.0.0.1,.local
220+
199221
.TP
200222
.B CloneDir = /path/to/dir
201223
Directory used to download and run PKGBUILDs.
@@ -208,7 +230,7 @@ visible here: https://aur.archlinux.org/packages/
208230

209231
.TP
210232
.B SearchBy = <name|name-desc|maintainer|depends|checkdepends|makedepends|optdepends>
211-
Defaults to name-desc. Search AUR packages according to the options in
233+
Defaults to name-desc. Search AUR packages according to the options in
212234
"Search by" visible here: https://aur.archlinux.org/packages/
213235

214236
.TP

src/command_line.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ impl Config {
173173
Arg::Long("version") | Arg::Short('V') => self.version = true,
174174
Arg::Long("aururl") => self.aur_url = Url::parse(value?)?,
175175
Arg::Long("aurrpcurl") => self.aur_rpc_url = Some(Url::parse(value?)?),
176+
Arg::Long("proxy") => self.proxy = Some(value?.to_string()),
177+
Arg::Long("noproxy") => self.no_proxy = Some(value?.to_string()),
176178
Arg::Long("makepkg") => self.makepkg_bin = value?.to_string(),
177179
Arg::Long("pacman") => self.pacman_bin = value?.to_string(),
178180
Arg::Long("pacman-conf") => self.pacman_conf_bin = Some(value?.to_string()),
@@ -395,6 +397,8 @@ fn takes_value(arg: Arg) -> TakesValue {
395397
match arg {
396398
Arg::Long("aururl") => TakesValue::Required,
397399
Arg::Long("aurrpcurl") => TakesValue::Required,
400+
Arg::Long("proxy") => TakesValue::Required,
401+
Arg::Long("noproxy") => TakesValue::Required,
398402
Arg::Long("editor") => TakesValue::Required,
399403
Arg::Long("makepkg") => TakesValue::Required,
400404
Arg::Long("pacman") => TakesValue::Required,

src/completion.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ use reqwest::get;
1212
use tr::tr;
1313
use url::Url;
1414

15-
async fn save_aur_list(aur_url: &Url, cache_dir: &Path) -> Result<()> {
15+
async fn save_aur_list(client: &reqwest::Client, aur_url: &Url, cache_dir: &Path) -> Result<()> {
1616
let url = aur_url.join("packages.gz")?;
17-
let resp = get(url.clone())
17+
let resp = client
18+
.get(url.clone())
19+
.send()
1820
.await
1921
.with_context(|| format!("get {}", url))?;
2022
let success = resp.status().is_success();
@@ -42,7 +44,12 @@ async fn save_aur_list(aur_url: &Url, cache_dir: &Path) -> Result<()> {
4244
Ok(())
4345
}
4446

45-
pub async fn update_aur_cache(aur_url: &Url, cache_dir: &Path, timeout: Option<u64>) -> Result<()> {
47+
pub async fn update_aur_cache(
48+
client: &reqwest::Client,
49+
aur_url: &Url,
50+
cache_dir: &Path,
51+
timeout: Option<u64>,
52+
) -> Result<()> {
4653
let path = cache_dir.join("packages.aur");
4754
let metadata = metadata(&path);
4855

@@ -71,14 +78,15 @@ pub async fn update_aur_cache(aur_url: &Url, cache_dir: &Path, timeout: Option<u
7178
};
7279

7380
if need_refresh {
74-
save_aur_list(aur_url, cache_dir).await?;
81+
save_aur_list(client, aur_url, cache_dir).await?;
7582
}
7683

7784
Ok(())
7885
}
7986

8087
async fn aur_list<W: Write>(config: &Config, w: &mut W, timeout: Option<u64>) -> Result<()> {
81-
update_aur_cache(&config.aur_url, &config.cache_dir, timeout)
88+
let client = config.raur.client();
89+
update_aur_cache(&client, &config.aur_url, &config.cache_dir, timeout)
8290
.await
8391
.context(tr!("could not update aur cache"))?;
8492
let path = config.cache_dir.join("packages.aur");

src/config.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,8 @@ pub struct Config {
409409
pub aur_rpc_url: Option<Url>,
410410
#[default(Url::parse("https://archlinux.org").unwrap())]
411411
pub arch_url: Url,
412+
pub proxy: Option<String>,
413+
pub no_proxy: Option<String>,
412414
pub build_dir: PathBuf,
413415
pub cache_dir: PathBuf,
414416
pub state_dir: PathBuf,
@@ -728,10 +730,20 @@ impl Config {
728730
use std::time::Duration;
729731

730732
let ver = option_env!("PARU_VERSION").unwrap_or(env!("CARGO_PKG_VERSION"));
731-
let client = reqwest::Client::builder()
733+
let mut builder = reqwest::Client::builder()
732734
.tcp_keepalive(Duration::new(15, 0))
733-
.user_agent(format!("paru/{}", ver))
734-
.build()?;
735+
.user_agent(format!("paru/{}", ver));
736+
737+
if let Some(ref proxy_url) = self.proxy {
738+
let mut proxy = reqwest::Proxy::all(proxy_url)
739+
.with_context(|| format!("invalid proxy URL: {}", proxy_url))?;
740+
if let Some(ref no_proxy) = self.no_proxy {
741+
proxy = proxy.no_proxy(reqwest::NoProxy::from_string(no_proxy));
742+
}
743+
builder = builder.proxy(proxy);
744+
}
745+
746+
let client = builder.build()?;
735747

736748
let rpc_url = match &self.aur_rpc_url {
737749
Some(rpc) => rpc.to_string(),
@@ -1108,6 +1120,8 @@ then initialise it with:
11081120
}
11091121
"AurUrl" => self.aur_url = value?.parse()?,
11101122
"AurRpcUrl" => self.aur_rpc_url = Some(value?.parse()?),
1123+
"Proxy" => self.proxy = Some(value?.to_string()),
1124+
"NoProxy" => self.no_proxy = Some(value?.to_string()),
11111125
"BuildDir" | "CloneDir" => self.build_dir = PathBuf::from(value?),
11121126
"Redownload" => self.redownload = ConfigEnum::from_str(key, value?.as_str())?,
11131127
"Rebuild" => self.rebuild = ConfigEnum::from_str(key, value?.as_str())?,

src/help.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ pub fn help() {
3838
);
3939
printtr!(" --aururl <url> Set an alternative AUR URL");
4040
printtr!(" --aurrpcur <url> Set an alternative URL for the AUR /rpc endpoint");
41+
printtr!(" --proxy <url> Set HTTP proxy for AUR requests");
42+
printtr!(" --noproxy <list> Comma-separated hosts to bypass proxy");
4143
printtr!(" --clonedir <dir> Directory used to download and run PKGBUILDs");
4244
println!();
4345
printtr!(" --makepkg <file> makepkg command to use");

src/install.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1801,12 +1801,13 @@ pub fn review(config: &Config, fetch: &aur_fetch::Fetch, pkgs: &[&str]) -> Resul
18011801
}
18021802

18031803
fn update_aur_list(config: &Config) {
1804+
let client = config.raur.client().clone();
18041805
let url = config.aur_url.clone();
18051806
let dir = config.cache_dir.clone();
18061807
let interval = config.completion_interval;
18071808

18081809
tokio::spawn(async move {
1809-
let _ = update_aur_cache(&url, &dir, Some(interval)).await;
1810+
let _ = update_aur_cache(&client, &url, &dir, Some(interval)).await;
18101811
});
18111812
}
18121813

src/search.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use flate2::read::GzDecoder;
1212
use indicatif::HumanBytes;
1313
use raur::{Raur, SearchBy};
1414
use regex::RegexSet;
15-
use reqwest::get;
1615
use srcinfo::Srcinfo;
1716
use tr::tr;
1817

@@ -167,7 +166,10 @@ async fn search_target(config: &Config, targets: &mut Vec<String>) -> Result<Vec
167166

168167
async fn search_aur_regex(config: &Config, targets: &[String]) -> Result<Vec<raur::Package>> {
169168
let url = config.aur_url.join("packages.gz")?;
170-
let resp = get(url.clone())
169+
let client = config.raur.client();
170+
let resp = client
171+
.get(url.clone())
172+
.send()
171173
.await
172174
.with_context(|| format!("get {}", url))?;
173175
let success = resp.status().is_success();

0 commit comments

Comments
 (0)