feat: remove anyhow dependency and replace with custom error handling; update validation error types
parent
9e88973ef7
commit
660367d8a3
|
@ -76,12 +76,6 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
||||
|
||||
[[package]]
|
||||
name = "async-stream"
|
||||
version = "0.3.6"
|
||||
|
@ -387,7 +381,6 @@ dependencies = [
|
|||
name = "gemini-keychecker"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
"backon",
|
||||
"clap",
|
||||
|
|
|
@ -5,7 +5,6 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
mimalloc = { version = "*" }
|
||||
anyhow = "1.0"
|
||||
backon = "1"
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
futures = "0.3"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::adapters::output::write_keys_to_file;
|
||||
use crate::types::GeminiKey;
|
||||
use anyhow::Result;
|
||||
use crate::error::Result;
|
||||
use std::{collections::HashSet, fs, path::Path, str::FromStr};
|
||||
|
||||
/// Load and validate API keys from a file
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::types::GeminiKey;
|
||||
use anyhow::Result;
|
||||
use crate::error::Result;
|
||||
use std::{fs, io::Write};
|
||||
use tokio::io::{AsyncWriteExt, BufWriter};
|
||||
use toml::Value;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::Result;
|
||||
use crate::error::ValidationError;
|
||||
use clap::Parser;
|
||||
use figment::{
|
||||
Figment,
|
||||
|
@ -85,7 +85,7 @@ impl Default for KeyCheckerConfig {
|
|||
}
|
||||
}
|
||||
impl KeyCheckerConfig {
|
||||
pub fn load_config() -> Result<Self> {
|
||||
pub fn load_config() -> Result<Self, ValidationError> {
|
||||
// Define the path to the configuration file
|
||||
static CONFIG_PATH: LazyLock<PathBuf> = LazyLock::new(|| "Config.toml".into());
|
||||
|
||||
|
@ -167,8 +167,6 @@ pub static TEST_MESSAGE_BODY: LazyLock<Value> = LazyLock::new(|| {
|
|||
})
|
||||
});
|
||||
|
||||
|
||||
|
||||
fn default_api_host() -> Url {
|
||||
DEFAULT_CONFIG.api_host.clone()
|
||||
}
|
||||
|
|
26
src/error.rs
26
src/error.rs
|
@ -3,13 +3,31 @@ use thiserror::Error;
|
|||
#[derive(Error, Debug)]
|
||||
pub enum ValidationError {
|
||||
#[error("HTTP error: {0}")]
|
||||
HttpRequest(#[from] reqwest::Error),
|
||||
ReqwestError(#[from] reqwest::Error),
|
||||
|
||||
#[error("Key is unavailable or invalid")]
|
||||
KeyUnavailable,
|
||||
|
||||
KeyInvalid,
|
||||
|
||||
#[error("IO error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
|
||||
#[error("Configuration error: {0}")]
|
||||
ConfigError(#[from] figment::Error),
|
||||
|
||||
#[error("TOML serialization error: {0}")]
|
||||
TomlSer(#[from] toml::ser::Error),
|
||||
|
||||
#[error("TOML deserialization error: {0}")]
|
||||
TomlDe(#[from] toml::de::Error),
|
||||
|
||||
#[error("JSON error: {0}")]
|
||||
Json(#[from] serde_json::Error),
|
||||
|
||||
#[error("URL parse error: {0}")]
|
||||
UrlParse(#[from] url::ParseError),
|
||||
|
||||
#[error("Key validation failed: {0}")]
|
||||
Invalid(String),
|
||||
Validation(String),
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, ValidationError>;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::Result;
|
||||
use gemini_keychecker::error::ValidationError;
|
||||
use gemini_keychecker::{BANNER, config::KeyCheckerConfig, service::start_validation};
|
||||
|
||||
use mimalloc::MiMalloc;
|
||||
|
@ -8,7 +8,7 @@ static GLOBAL: MiMalloc = MiMalloc;
|
|||
|
||||
/// Main function - displays banner and starts validation service
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
async fn main() -> Result<(), ValidationError> {
|
||||
// Display banner and configuration status at startup
|
||||
println!("{BANNER}");
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::config::KeyCheckerConfig;
|
||||
use crate::{config::KeyCheckerConfig, error::ValidationError};
|
||||
use reqwest::Client;
|
||||
use std::time::Duration;
|
||||
|
||||
pub fn client_builder(config: &KeyCheckerConfig) -> Result<Client, reqwest::Error> {
|
||||
pub fn client_builder(config: &KeyCheckerConfig) -> Result<Client, ValidationError> {
|
||||
// Set the maximum number of connections per host based on concurrency.
|
||||
let pool_size = config.concurrency / 2;
|
||||
|
||||
|
@ -18,5 +18,5 @@ pub fn client_builder(config: &KeyCheckerConfig) -> Result<Client, reqwest::Erro
|
|||
builder = builder.http1_only();
|
||||
}
|
||||
|
||||
builder.build()
|
||||
Ok(builder.build()?)
|
||||
}
|
||||
|
|
|
@ -21,13 +21,13 @@ pub async fn validate_key(
|
|||
StatusCode::OK => Ok(api_key),
|
||||
StatusCode::UNAUTHORIZED
|
||||
| StatusCode::FORBIDDEN
|
||||
| StatusCode::TOO_MANY_REQUESTS => Err(ValidationError::KeyUnavailable),
|
||||
_ => Err(ValidationError::HttpRequest(
|
||||
| StatusCode::TOO_MANY_REQUESTS => Err(ValidationError::KeyInvalid),
|
||||
_ => Err(ValidationError::ReqwestError(
|
||||
response.error_for_status().unwrap_err(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
Err(e) => Err(ValidationError::HttpRequest(e)),
|
||||
Err(e) => Err(ValidationError::ReqwestError(e)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use anyhow::Result;
|
||||
use crate::error::ValidationError;
|
||||
use async_stream::stream;
|
||||
use futures::{pin_mut, stream::StreamExt};
|
||||
use reqwest::Client;
|
||||
use std::time::Instant;
|
||||
use tokio::{fs, io::AsyncWriteExt, sync::mpsc};
|
||||
|
||||
use super::{key_tester::validate_key, http_client::client_builder};
|
||||
use crate::adapters::{write_keys_txt_file, load_keys};
|
||||
use super::{http_client::client_builder, key_tester::validate_key};
|
||||
use crate::adapters::{load_keys, write_keys_txt_file};
|
||||
use crate::config::KeyCheckerConfig;
|
||||
use crate::types::GeminiKey;
|
||||
|
||||
|
@ -26,7 +26,7 @@ impl ValidationService {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn validate_keys(&self, keys: Vec<GeminiKey>) -> Result<()> {
|
||||
pub async fn validate_keys(&self, keys: Vec<GeminiKey>) -> Result<(), ValidationError> {
|
||||
let start_time = Instant::now();
|
||||
|
||||
// Create channel for streaming keys from producer to consumer
|
||||
|
@ -74,15 +74,15 @@ impl ValidationService {
|
|||
}
|
||||
|
||||
/// 启动验证服务 - 封装了所有启动逻辑
|
||||
pub async fn start_validation() -> Result<()> {
|
||||
pub async fn start_validation() -> Result<(), ValidationError> {
|
||||
let config = KeyCheckerConfig::load_config()?;
|
||||
|
||||
|
||||
// 加载密钥
|
||||
let keys = load_keys(config.input_path.as_path())?;
|
||||
|
||||
|
||||
// 构建HTTP客户端
|
||||
let client = client_builder(&config)?;
|
||||
|
||||
|
||||
// 创建验证服务并启动
|
||||
let validation_service = ValidationService::new(config, client);
|
||||
validation_service.validate_keys(keys).await
|
||||
|
|
Loading…
Reference in New Issue