use crate::error::ApiError;
pub const USAGE_API_URL: &str = "https://api.anthropic.com/api/oauth/usage";
pub const BETA_HEADER: &str = "oauth-2025-04-20";
#[cfg(feature = "blocking")]
pub fn fetch_usage_raw(token: &str) -> Result<String, ApiError> {
let client = reqwest::blocking::Client::new();
let response = client
.get(USAGE_API_URL)
.header("Authorization", format!("Bearer {}", token))
.header("anthropic-beta", BETA_HEADER)
.send()
.map_err(|_| ApiError::Network("Failed to connect to Anthropic API".to_string()))?;
map_response(response)
}
#[cfg(feature = "blocking")]
fn map_response(response: reqwest::blocking::Response) -> Result<String, ApiError> {
let status = response.status().as_u16();
match status {
200 => response
.text()
.map_err(|_| ApiError::Network("Failed to read response body".to_string())),
401 => Err(ApiError::Unauthorized),
429 => {
let retry_after = response
.headers()
.get("retry-after")
.and_then(|v| v.to_str().ok())
.map(String::from);
Err(ApiError::RateLimited { retry_after })
}
500..=599 => Err(ApiError::Server(status)),
_ => Err(ApiError::Unexpected(status)),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_api_url_is_correct() {
assert_eq!(USAGE_API_URL, "https://api.anthropic.com/api/oauth/usage");
}
#[test]
fn test_beta_header_is_correct() {
assert_eq!(BETA_HEADER, "oauth-2025-04-20");
}
#[test]
#[ignore = "requires real API credentials"]
#[cfg(feature = "blocking")]
fn test_fetch_usage_raw_integration() {
let token = std::env::var("CLAUDE_CODE_OAUTH_TOKEN")
.expect("CLAUDE_CODE_OAUTH_TOKEN must be set for integration test");
let result = fetch_usage_raw(&token);
match result {
Ok(body) => {
assert!(body.contains("five_hour"));
assert!(body.contains("seven_day"));
println!("API response received successfully");
}
Err(ApiError::Unauthorized) => {
println!("Token is invalid or expired");
}
Err(e) => {
panic!("Unexpected error: {}", e);
}
}
}
#[test]
#[cfg(feature = "blocking")]
fn test_fetch_with_invalid_token() {
let result = fetch_usage_raw("invalid-token");
assert!(matches!(result, Err(ApiError::Unauthorized)));
}
}