use crate::models::{ResponseStatus, ServerResponse};
use axum::{
body::{Body, Bytes},
extract::Request,
http::{self, StatusCode},
response::IntoResponse,
Json,
};
use hyper::Uri;
use tracing;
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)
}