mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-25 13:45:03 +08:00
Fix/Resolve panic issues in proxy-related code (#560)
* fix(proxy): change default port from 5000 to 15721 Port 5000 conflicts with AirPlay Receiver on macOS 12+. Also adds error handling for proxy toggle and i18n placeholder updates. * fix(proxy): replace unwrap/expect with graceful error handling - Handle HTTP client initialization failure with no_proxy fallback - Fix potential panic on Unicode slicing in API key preview - Add proper error handling for response body builder - Handle edge case where SystemTime is before UNIX_EPOCH * fix(proxy): handle UTF-8 char boundary when truncating request body log Rust strings are UTF-8 encoded, slicing at a fixed byte index may cut in the middle of a multi-byte character (e.g., Chinese, emoji), causing a panic. Use is_char_boundary() to find the nearest safe cut point. * fix(proxy): improve robustness and prevent panics - Add reqwest socks feature to support SOCKS proxy environments - Fix UTF-8 safety in masked_key/masked_access_token (use chars() instead of byte slicing) - Fix UTF-8 boundary check in usage_script HTTP response truncation - Add defensive checks for JSON operations in proxy service - Remove verbose debug logs that could trigger panic-prone code paths
This commit is contained in:
@@ -38,13 +38,20 @@ impl AuthInfo {
|
||||
///
|
||||
/// 显示前4位和后4位,中间用 `...` 代替
|
||||
/// 如果 key 长度不足8位,则返回 `***`
|
||||
#[allow(dead_code)]
|
||||
pub fn masked_key(&self) -> String {
|
||||
if self.api_key.len() > 8 {
|
||||
format!(
|
||||
"{}...{}",
|
||||
&self.api_key[..4],
|
||||
&self.api_key[self.api_key.len() - 4..]
|
||||
)
|
||||
if self.api_key.chars().count() > 8 {
|
||||
let prefix: String = self.api_key.chars().take(4).collect();
|
||||
let suffix: String = self
|
||||
.api_key
|
||||
.chars()
|
||||
.rev()
|
||||
.take(4)
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.rev()
|
||||
.collect();
|
||||
format!("{prefix}...{suffix}")
|
||||
} else {
|
||||
"***".to_string()
|
||||
}
|
||||
@@ -54,8 +61,17 @@ impl AuthInfo {
|
||||
#[allow(dead_code)]
|
||||
pub fn masked_access_token(&self) -> Option<String> {
|
||||
self.access_token.as_ref().map(|token| {
|
||||
if token.len() > 8 {
|
||||
format!("{}...{}", &token[..4], &token[token.len() - 4..])
|
||||
if token.chars().count() > 8 {
|
||||
let prefix: String = token.chars().take(4).collect();
|
||||
let suffix: String = token
|
||||
.chars()
|
||||
.rev()
|
||||
.take(4)
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.rev()
|
||||
.collect();
|
||||
format!("{prefix}...{suffix}")
|
||||
} else {
|
||||
"***".to_string()
|
||||
}
|
||||
@@ -126,6 +142,13 @@ mod tests {
|
||||
assert_eq!(auth.masked_key(), "1234...6789");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_masked_key_utf8_safe() {
|
||||
let auth = AuthInfo::new("测试⚠️1234567890".to_string(), AuthStrategy::Bearer);
|
||||
let masked = auth.masked_key();
|
||||
assert!(!masked.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_auth_strategy_equality() {
|
||||
assert_eq!(AuthStrategy::Anthropic, AuthStrategy::Anthropic);
|
||||
@@ -160,6 +183,14 @@ mod tests {
|
||||
assert_eq!(auth.masked_access_token(), Some("ya29...cdef".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_masked_access_token_utf8_safe() {
|
||||
let auth =
|
||||
AuthInfo::with_access_token("refresh".to_string(), "令牌⚠️1234567890".to_string());
|
||||
let masked = auth.masked_access_token().unwrap();
|
||||
assert!(!masked.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_masked_access_token_short() {
|
||||
let auth = AuthInfo::with_access_token("refresh".to_string(), "short".to_string());
|
||||
|
||||
Reference in New Issue
Block a user