use axum::{
body::Body,
http::{Request, StatusCode},
};
use tower::util::ServiceExt;
use crate::api::*;
fn router_with(cors: bool, metrics: bool) -> axum::Router {
let state = AppState::with_cache(10);
create_router_with_config(
state,
RouterConfig {
openai_api: true,
cors,
metrics,
},
)
}
async fn get(app: axum::Router, uri: &str) -> axum::http::Response<Body> {
app.oneshot(
Request::builder()
.method("GET")
.uri(uri)
.header("origin", "http://example.invalid")
.body(Body::empty())
.expect("request builds"),
)
.await
.expect("router responds")
}
async fn body_string(response: axum::http::Response<Body>) -> String {
let bytes = axum::body::to_bytes(response.into_body(), 1024 * 1024)
.await
.expect("body collects");
String::from_utf8_lossy(&bytes).into_owned()
}
#[tokio::test]
async fn metrics_enabled_serves_prometheus_exposition() {
let response = get(router_with(true, true), "/metrics").await;
assert_eq!(response.status(), StatusCode::OK);
let body = body_string(response).await;
assert!(
body.contains("realizar_requests_total"),
"enabled /metrics must expose the counter set, got: {body}"
);
}
#[tokio::test]
async fn metrics_disabled_makes_metrics_endpoints_404() {
for uri in ["/metrics", "/metrics/dispatch"] {
let response = get(router_with(true, false), uri).await;
assert_eq!(
response.status(),
StatusCode::NOT_FOUND,
"{uri} must 404 when metrics are disabled"
);
let body = body_string(response).await;
assert!(
!body.contains("realizar_requests_total"),
"{uri} leaked metrics while disabled: {body}"
);
}
}
#[tokio::test]
async fn metrics_disabled_keeps_health_serving() {
let response = get(router_with(true, false), "/health").await;
assert_eq!(response.status(), StatusCode::OK);
}
#[tokio::test]
async fn cors_enabled_sends_allow_origin_header() {
let response = get(router_with(true, true), "/health").await;
assert_eq!(
response
.headers()
.get("access-control-allow-origin")
.map(|v| v.to_str().unwrap_or_default().to_owned()),
Some("*".to_owned()),
"CORS-enabled server must advertise a permissive origin"
);
}
#[tokio::test]
async fn cors_disabled_sends_no_access_control_headers() {
let response = get(router_with(false, true), "/health").await;
assert_eq!(response.status(), StatusCode::OK);
let leaked: Vec<String> = response
.headers()
.keys()
.map(|k| k.as_str().to_owned())
.filter(|k| k.starts_with("access-control"))
.collect();
assert!(
leaked.is_empty(),
"CORS-disabled server still sent: {leaked:?}"
);
}
#[tokio::test]
async fn cors_disabled_does_not_answer_preflight_permissively() {
let response = router_with(false, true)
.oneshot(
Request::builder()
.method("OPTIONS")
.uri("/health")
.header("origin", "http://example.invalid")
.header("access-control-request-method", "POST")
.body(Body::empty())
.expect("request builds"),
)
.await
.expect("router responds");
let leaked: Vec<String> = response
.headers()
.keys()
.map(|k| k.as_str().to_owned())
.filter(|k| k.starts_with("access-control"))
.collect();
assert!(
leaked.is_empty(),
"CORS-disabled preflight still sent: {leaked:?}"
);
}