use axum::{middleware::Next, response::IntoResponse};
use tower_http::cors::{Any, CorsLayer};
pub fn cors_layer() -> CorsLayer {
tracing::warn!(
"Using permissive CORS settings (allows all origins). \
This is suitable for development only. \
For production, configure cors_origins in server config and use cors_layer_restricted()."
);
CorsLayer::new()
.allow_origin(Any)
.allow_methods(Any)
.allow_headers(Any)
.expose_headers(Any)
}
pub fn cors_layer_restricted(allowed_origins: &[String]) -> CorsLayer {
let origins: Vec<_> = allowed_origins.iter().filter_map(|origin| origin.parse().ok()).collect();
CorsLayer::new()
.allow_origin(origins)
.allow_methods([
axum::http::Method::GET,
axum::http::Method::POST,
axum::http::Method::OPTIONS,
])
.allow_headers([
axum::http::header::CONTENT_TYPE,
axum::http::header::AUTHORIZATION,
])
}
pub async fn security_headers_middleware(
req: axum::extract::Request,
next: Next,
) -> impl IntoResponse {
let mut response = next.run(req).await;
let headers = response.headers_mut();
headers.insert("X-Content-Type-Options", "nosniff".parse().expect("valid header value"));
headers.insert("X-Frame-Options", "DENY".parse().expect("valid header value"));
headers.insert(
"Strict-Transport-Security",
"max-age=31536000; includeSubDomains".parse().expect("valid header value"),
);
headers.insert(
"Referrer-Policy",
"strict-origin-when-cross-origin".parse().expect("valid header value"),
);
headers.insert(
"Content-Security-Policy",
"default-src 'self'; script-src 'self'; style-src 'self'"
.parse()
.expect("valid header value"),
);
headers.insert("X-XSS-Protection", "0".parse().expect("valid header value"));
response
}