llmproxy 0.2.2

A simple HTTP proxy server for llm api requests
Documentation
use crate::models::{ResponseStatus, ServerResponse};
use axum::{
    body::{Body, Bytes},
    extract::Request,
    http::{self, StatusCode},
    response::IntoResponse,
    Json,
};
use hyper::Uri;
use tracing;

/// Build a proxy request to forward to the target server
pub fn build_proxy_request(
    parts: http::request::Parts,
    body_bytes: Bytes,
    target_addr: &str,
) -> Result<Request, Box<axum::response::Response>> {
    let path_and_query = parts
        .uri
        .path_and_query()
        .map(|x| x.as_str())
        .unwrap_or("/");

    let scheme = "http://";
    let host = target_addr
        .trim_start_matches("http://")
        .trim_start_matches("https://");
    let target_uri_str = format!("{scheme}{host}{path_and_query}");

    let target_uri: Uri = match target_uri_str.parse() {
        Ok(uri) => uri,
        Err(e) => {
            tracing::error!("Failed to parse target URI '{target_uri_str}': {e}");
            return Err(Box::new(
                (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    Json(ServerResponse {
                        status: ResponseStatus::Error,
                        message: "Failed to construct target URI".to_string(),
                    }),
                )
                    .into_response(),
            ));
        }
    };

    let req_body = Body::from(body_bytes);

    let mut builder = Request::builder()
        .method(parts.method.clone())
        .uri(target_uri);

    if let Some(headers_mut) = builder.headers_mut() {
        *headers_mut = parts.headers.clone();
    } else {
        tracing::error!("Failed to get mutable headers from builder");
        return Err(Box::new(
            (StatusCode::INTERNAL_SERVER_ERROR, "Error building request").into_response(),
        ));
    }

    let new_req = match builder.body(req_body) {
        Ok(req) => req,
        Err(e) => {
            tracing::error!("Failed to build proxy request: {}", e);
            return Err(Box::new(
                (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    Json(ServerResponse {
                        status: ResponseStatus::Error,
                        message: "Failed to build proxy request".to_string(),
                    }),
                )
                    .into_response(),
            ));
        }
    };

    tracing::debug!(?new_req, "Forwarding request");
    Ok(new_req)
}