use axum::{
extract::{Request, State},
http::HeaderValue,
middleware::Next,
response::Response,
};
use crate::api::cors::match_cors_rule;
use crate::AppState;
const INTERNAL_SEGMENTS: &[&str] = &[
"health",
"ready",
"metrics",
"api",
"graphql",
"events",
"swagger-ui",
"openapi.json",
"presign",
"WriteGetObjectResponse",
];
pub async fn cors_simple_request(
State(state): State<AppState>,
request: Request,
next: Next,
) -> Response {
let origin = request
.headers()
.get("origin")
.and_then(|v| v.to_str().ok())
.map(|s| s.to_string());
let origin = match origin {
Some(o) => o,
None => return next.run(request).await,
};
let path = request.uri().path().to_string();
let bucket = path
.split('/')
.find(|s| !s.is_empty())
.map(|s| s.to_string());
let method = request.method().as_str().to_string();
let mut response = next.run(request).await;
let bucket = match bucket {
Some(b) if !INTERNAL_SEGMENTS.contains(&b.as_str()) => b,
_ => return response,
};
let cfg = match state.storage.get_bucket_cors(&bucket).await {
Ok(c) => c,
Err(_) => return response,
};
let rule = match match_cors_rule(&cfg, &origin, &method, &[]) {
Some(r) => r,
None => return response,
};
let h = response.headers_mut();
if let Ok(v) = HeaderValue::from_str(&origin) {
h.insert("access-control-allow-origin", v);
}
let expose = rule.expose_headers.join(",");
if !expose.is_empty() {
if let Ok(v) = HeaderValue::from_str(&expose) {
h.insert("access-control-expose-headers", v);
}
}
h.insert("vary", HeaderValue::from_static("Origin"));
response
}