Skip to content

Commit 0e802af

Browse files
committed
feat: add API proxy support for GitLab and Codeberg
1 parent 5d85807 commit 0e802af

File tree

3 files changed

+104
-41
lines changed

3 files changed

+104
-41
lines changed

src/config.rs

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,45 @@ impl StringOrVec {
2828
#[derive(Debug, Default, Deserialize)]
2929
pub struct Config {
3030
pub github_api_proxy: Option<StringOrVec>,
31+
pub gitlab_api_proxy: Option<StringOrVec>,
32+
pub codeberg_api_proxy: Option<StringOrVec>,
3133
pub remove_old: Option<bool>,
3234
pub output_dir: Option<PathBuf>,
3335
}
3436

3537
static CONFIG: OnceLock<Config> = OnceLock::new();
36-
static PROXIES: OnceLock<Vec<String>> = OnceLock::new();
38+
static GITHUB_PROXIES: OnceLock<Vec<String>> = OnceLock::new();
39+
static GITLAB_PROXIES: OnceLock<Vec<String>> = OnceLock::new();
40+
static CODEBERG_PROXIES: OnceLock<Vec<String>> = OnceLock::new();
3741

3842
pub fn init() {
3943
let config = load_config();
4044
let _ = CONFIG.set(config);
4145
}
4246

43-
pub fn set_proxies(proxies: Vec<String>) {
47+
pub fn set_github_proxies(proxies: Vec<String>) {
4448
if !proxies.is_empty() {
45-
let _ = PROXIES.set(proxies);
49+
let _ = GITHUB_PROXIES.set(proxies);
50+
}
51+
}
52+
53+
pub fn set_gitlab_proxies(proxies: Vec<String>) {
54+
if !proxies.is_empty() {
55+
let _ = GITLAB_PROXIES.set(proxies);
56+
}
57+
}
58+
59+
pub fn set_codeberg_proxies(proxies: Vec<String>) {
60+
if !proxies.is_empty() {
61+
let _ = CODEBERG_PROXIES.set(proxies);
4662
}
4763
}
4864

4965
pub fn get() -> &'static Config {
5066
static DEFAULT: Config = Config {
5167
github_api_proxy: None,
68+
gitlab_api_proxy: None,
69+
codeberg_api_proxy: None,
5270
remove_old: None,
5371
output_dir: None,
5472
};
@@ -80,20 +98,38 @@ fn try_load_config(path: PathBuf) -> Option<Config> {
8098
.and_then(|content| toml::from_str(&content).ok())
8199
}
82100

83-
pub fn get_proxies() -> Vec<String> {
84-
if let Some(proxies) = PROXIES.get() {
101+
pub fn get_github_proxies() -> Vec<String> {
102+
get_forge_proxies(&GITHUB_PROXIES, "GITHUB_API_PROXY", |c| {
103+
c.github_api_proxy.as_ref()
104+
})
105+
}
106+
107+
pub fn get_gitlab_proxies() -> Vec<String> {
108+
get_forge_proxies(&GITLAB_PROXIES, "GITLAB_API_PROXY", |c| {
109+
c.gitlab_api_proxy.as_ref()
110+
})
111+
}
112+
113+
pub fn get_codeberg_proxies() -> Vec<String> {
114+
get_forge_proxies(&CODEBERG_PROXIES, "CODEBERG_API_PROXY", |c| {
115+
c.codeberg_api_proxy.as_ref()
116+
})
117+
}
118+
119+
fn get_forge_proxies(
120+
cli_proxies: &OnceLock<Vec<String>>,
121+
env_var: &str,
122+
config_field: impl FnOnce(&Config) -> Option<&StringOrVec>,
123+
) -> Vec<String> {
124+
if let Some(proxies) = cli_proxies.get() {
85125
return proxies.clone();
86126
}
87127

88-
if let Ok(s) = std::env::var("GITHUB_API_PROXY") {
128+
if let Ok(s) = std::env::var(env_var) {
89129
return parse_proxies(&s);
90130
}
91131

92-
get()
93-
.github_api_proxy
94-
.as_ref()
95-
.map(|v| v.to_vec())
96-
.unwrap_or_default()
132+
config_field(get()).map(|v| v.to_vec()).unwrap_or_default()
97133
}
98134

99135
pub fn get_remove_old(cli_value: Option<bool>) -> bool {
@@ -131,13 +167,3 @@ fn parse_proxies(s: &str) -> Vec<String> {
131167
.filter(|s| !s.is_empty())
132168
.collect()
133169
}
134-
135-
pub fn build_api_url(path: &str, proxy: Option<&str>) -> String {
136-
match proxy {
137-
Some(proxy) => {
138-
let proxy = proxy.trim_end_matches('/');
139-
format!("{}{}", proxy, path)
140-
}
141-
None => format!("https://api.github.com{}", path),
142-
}
143-
}

src/main.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,22 @@ struct Cli {
4545
)]
4646
github_api_proxy: Vec<String>,
4747

48+
#[arg(
49+
long,
50+
value_name = "URL",
51+
env = "GITLAB_API_PROXY",
52+
value_delimiter = ','
53+
)]
54+
gitlab_api_proxy: Vec<String>,
55+
56+
#[arg(
57+
long,
58+
value_name = "URL",
59+
env = "CODEBERG_API_PROXY",
60+
value_delimiter = ','
61+
)]
62+
codeberg_api_proxy: Vec<String>,
63+
4864
#[arg(short = 'J', long, value_name = "N", default_value = "0")]
4965
jobs: usize,
5066
}
@@ -69,7 +85,13 @@ fn main() {
6985

7086
fn run(cli: Cli) -> Result<(), Error> {
7187
if !cli.github_api_proxy.is_empty() {
72-
config::set_proxies(cli.github_api_proxy.clone());
88+
config::set_github_proxies(cli.github_api_proxy.clone());
89+
}
90+
if !cli.gitlab_api_proxy.is_empty() {
91+
config::set_gitlab_proxies(cli.gitlab_api_proxy.clone());
92+
}
93+
if !cli.codeberg_api_proxy.is_empty() {
94+
config::set_codeberg_proxies(cli.codeberg_api_proxy.clone());
7395
}
7496
if cli.paths.is_empty() {
7597
return Err(Error::AppImage(

src/update_info/forge.rs

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,32 @@ impl ForgeUpdateInfo {
5353

5454
fn resolve_url(&self) -> Result<String> {
5555
match &self.kind {
56-
ForgeKind::GitHub => self.resolve_github(),
57-
ForgeKind::GitLab => {
58-
let gl = GitLab::new(UreqClient).with_token_from_env(&["GITLAB_TOKEN", "GL_TOKEN"]);
59-
self.fetch_with_forge(gl)
60-
}
61-
ForgeKind::Codeberg => {
62-
let cb = Gitea::new(UreqClient, "https://codeberg.org")
63-
.with_token_from_env(&["CODEBERG_TOKEN"]);
64-
self.fetch_with_forge(cb)
65-
}
56+
ForgeKind::GitHub => self.resolve_with_proxies(
57+
config::get_github_proxies(),
58+
|base| {
59+
GitHub::new(UreqClient)
60+
.with_base_url(base)
61+
.with_token_from_env(&["GITHUB_TOKEN", "GH_TOKEN"])
62+
},
63+
|| GitHub::new(UreqClient).with_token_from_env(&["GITHUB_TOKEN", "GH_TOKEN"]),
64+
),
65+
ForgeKind::GitLab => self.resolve_with_proxies(
66+
config::get_gitlab_proxies(),
67+
|base| {
68+
GitLab::new(UreqClient)
69+
.with_base_url(base)
70+
.with_token_from_env(&["GITLAB_TOKEN", "GL_TOKEN"])
71+
},
72+
|| GitLab::new(UreqClient).with_token_from_env(&["GITLAB_TOKEN", "GL_TOKEN"]),
73+
),
74+
ForgeKind::Codeberg => self.resolve_with_proxies(
75+
config::get_codeberg_proxies(),
76+
|base| Gitea::new(UreqClient, base).with_token_from_env(&["CODEBERG_TOKEN"]),
77+
|| {
78+
Gitea::new(UreqClient, "https://codeberg.org")
79+
.with_token_from_env(&["CODEBERG_TOKEN"])
80+
},
81+
),
6682
ForgeKind::Gitea { instance } => {
6783
let gt = Gitea::new(UreqClient, format!("https://{instance}"))
6884
.with_token_from_env(&["GITEA_TOKEN"]);
@@ -71,20 +87,19 @@ impl ForgeUpdateInfo {
7187
}
7288
}
7389

74-
fn resolve_github(&self) -> Result<String> {
75-
let proxies = config::get_proxies();
76-
90+
fn resolve_with_proxies<F: Forge>(
91+
&self,
92+
proxies: Vec<String>,
93+
make_proxy: impl Fn(&str) -> F,
94+
make_default: impl FnOnce() -> F,
95+
) -> Result<String> {
7796
if proxies.is_empty() {
78-
let gh = GitHub::new(UreqClient).with_token_from_env(&["GITHUB_TOKEN", "GH_TOKEN"]);
79-
return self.fetch_with_forge(gh);
97+
return self.fetch_with_forge(make_default());
8098
}
8199

82100
let mut last_error = None;
83101
for proxy in &proxies {
84-
let gh = GitHub::new(UreqClient)
85-
.with_base_url(proxy)
86-
.with_token_from_env(&["GITHUB_TOKEN", "GH_TOKEN"]);
87-
match self.fetch_with_forge(gh) {
102+
match self.fetch_with_forge(make_proxy(proxy)) {
88103
Ok(url) => return Ok(url),
89104
Err(e) => last_error = Some(e),
90105
}

0 commit comments

Comments
 (0)