feat: enhance error handling in OAuth URL building and client creation; improve tool argument sanitization

This commit is contained in:
asepharyana
2026-07-12 10:23:26 +07:00
parent 0cc60c12ce
commit bb621fdff2
10 changed files with 79 additions and 43 deletions
+5 -3
View File
@@ -57,9 +57,11 @@ fn urlencoding(s: &str) -> String {
let mut chars = s.chars();
while let Some(c) = chars.next() {
if c == '%' {
let hi = chars.next().and_then(|c| c.to_digit(16)).unwrap_or(0);
let lo = chars.next().and_then(|c| c.to_digit(16)).unwrap_or(0);
result.push(char::from((hi * 16 + lo) as u8));
match (chars.next().and_then(|c| c.to_digit(16)),
chars.next().and_then(|c| c.to_digit(16))) {
(Some(hi), Some(lo)) => result.push(char::from((hi * 16 + lo) as u8)),
_ => { result.push('%'); }
}
} else {
result.push(c);
}
+16 -1
View File
@@ -84,7 +84,22 @@ impl OAuthManager {
}
pub fn build_auth_url(&self, redirect_uri: &str, state: &str, code_challenge: &str) -> String {
let mut url = url::Url::parse(&self.config.auth_url).unwrap_or_else(|_| url::Url::parse("https://example.com").unwrap());
// Refuse to build a URL if `auth_url` is missing or invalid. Previously this
// silently fell back to https://example.com, which produced a valid-looking
// auth URL pointing at the wrong server and leaked client credentials in
// query params. Returning an empty string signals failure to callers, who
// can prompt the user to fix the OAuth config instead of starting a flow
// against a wrong host.
let mut url = match url::Url::parse(&self.config.auth_url) {
Ok(u) if !self.config.auth_url.is_empty() => u,
_ => {
eprintln!(
"warning: OAuth auth_url is missing or invalid ('{}'); aborting build_auth_url",
self.config.auth_url
);
return String::new();
}
};
url.query_pairs_mut()
.append_pair("response_type", "code")
.append_pair("client_id", &self.config.client_id)
+8 -2
View File
@@ -29,11 +29,17 @@ impl LlmClient {
} else {
model
};
let client = reqwest::blocking::Client::builder()
let client = match reqwest::blocking::Client::builder()
.timeout(REQUEST_TIMEOUT)
.connect_timeout(CONNECT_TIMEOUT)
.build()
.unwrap_or_else(|_| reqwest::blocking::Client::new());
{
Ok(c) => c,
Err(e) => {
eprintln!("warning: failed to build reqwest client with timeouts: {}. Using default client without timeouts.", e);
reqwest::blocking::Client::new()
}
};
LlmClient {
client,
api_key,