claude-code-api 0.1.3

OpenAI-compatible API gateway for Claude Code CLI
use axum::{
    extract::Request,
    http::StatusCode,
    middleware::Next,
    response::{IntoResponse, Response},
    Json,
};
use std::time::Instant;
use tracing::{error, warn};

use crate::models::error::{ErrorResponse, ErrorDetail};

pub async fn handle_errors(
    req: Request,
    next: Next,
) -> Response {
    let start = Instant::now();
    let path = req.uri().path().to_string();
    let method = req.method().to_string();
    
    let response = next.run(req).await;
    
    let elapsed = start.elapsed();
    let status = response.status();
    
    if status.is_server_error() {
        error!(
            "Server error: {} {} - Status: {} - Duration: {:?}",
            method, path, status, elapsed
        );
    } else if status.is_client_error() && status != StatusCode::NOT_FOUND {
        warn!(
            "Client error: {} {} - Status: {} - Duration: {:?}",
            method, path, status, elapsed
        );
    }
    
    response
}

#[allow(dead_code)]
pub async fn handle_panic(err: Box<dyn std::any::Any + Send + 'static>) -> Response {
    let details = if let Some(s) = err.downcast_ref::<String>() {
        s.clone()
    } else if let Some(s) = err.downcast_ref::<&str>() {
        s.to_string()
    } else {
        "Unknown panic".to_string()
    };
    
    error!("Panic occurred: {}", details);
    
    let error_response = ErrorResponse {
        error: ErrorDetail {
            message: "Internal server error".to_string(),
            r#type: "internal_error".to_string(),
            param: None,
            code: Some("panic".to_string()),
        },
    };
    
    (StatusCode::INTERNAL_SERVER_ERROR, Json(error_response)).into_response()
}