1use axum::extract::Request;
6use axum::http::{HeaderName, HeaderValue};
7use axum::middleware::Next;
8
9const SECURITY_HEADERS: &[(&str, &str)] = &[
11 ("x-content-type-options", "nosniff"),
12 ("x-frame-options", "DENY"),
13 ("referrer-policy", "strict-origin-when-cross-origin"),
14 (
15 "content-security-policy",
16 "default-src 'none'; frame-ancestors 'none'",
17 ),
18];
19
20pub async fn security_headers_middleware(req: Request, next: Next) -> axum::response::Response {
22 let mut response = next.run(req).await;
23 let headers = response.headers_mut();
24 for (name, value) in SECURITY_HEADERS {
25 if let (Ok(n), Ok(v)) = (
26 HeaderName::from_bytes(name.as_bytes()),
27 HeaderValue::from_str(value),
28 ) {
29 headers.insert(n, v);
30 }
31 }
32 response
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38
39 #[test]
40 fn security_headers_are_valid() {
41 for (name, value) in SECURITY_HEADERS {
42 assert!(
43 HeaderName::from_bytes(name.as_bytes()).is_ok(),
44 "invalid header name: {name}"
45 );
46 assert!(
47 HeaderValue::from_str(value).is_ok(),
48 "invalid header value: {value}"
49 );
50 }
51 }
52}