aster_forge_actix_middleware/
security_headers.rs

1//! Default security response headers for Actix Web services.
2//!
3//! These headers are intentionally limited to generic browser hardening. HSTS
4//! is not set here because Aster services usually sit behind an HTTPS reverse
5//! proxy, and that proxy should own HTTPS termination policy.
6
7use actix_web::middleware::DefaultHeaders;
8
9/// Value used for the `X-Frame-Options` response header.
10pub const X_FRAME_OPTIONS_VALUE: &str = "SAMEORIGIN";
11/// Value used for the `Referrer-Policy` response header.
12pub const REFERRER_POLICY_VALUE: &str = "strict-origin-when-cross-origin";
13/// Value used for the `X-Content-Type-Options` response header.
14pub const X_CONTENT_TYPE_OPTIONS_VALUE: &str = "nosniff";
15
16/// Builds the default security headers middleware.
17#[must_use]
18pub fn default_headers() -> DefaultHeaders {
19    DefaultHeaders::new()
20        .add(("X-Frame-Options", X_FRAME_OPTIONS_VALUE))
21        .add(("Referrer-Policy", REFERRER_POLICY_VALUE))
22        .add(("X-Content-Type-Options", X_CONTENT_TYPE_OPTIONS_VALUE))
23}
24
25#[cfg(test)]
26mod tests {
27    use super::{
28        REFERRER_POLICY_VALUE, X_CONTENT_TYPE_OPTIONS_VALUE, X_FRAME_OPTIONS_VALUE, default_headers,
29    };
30    use actix_web::{HttpResponse, http::header, test, web};
31
32    #[actix_web::test]
33    async fn default_headers_adds_security_headers() {
34        let app = test::init_service(
35            actix_web::App::new()
36                .wrap(default_headers())
37                .route("/", web::get().to(HttpResponse::Ok)),
38        )
39        .await;
40
41        let request = test::TestRequest::get().uri("/").to_request();
42        let response = test::call_service(&app, request).await;
43
44        assert_eq!(
45            response.headers().get("x-frame-options"),
46            Some(&header::HeaderValue::from_static(X_FRAME_OPTIONS_VALUE))
47        );
48        assert_eq!(
49            response.headers().get("referrer-policy"),
50            Some(&header::HeaderValue::from_static(REFERRER_POLICY_VALUE))
51        );
52        assert_eq!(
53            response.headers().get("x-content-type-options"),
54            Some(&header::HeaderValue::from_static(
55                X_CONTENT_TYPE_OPTIONS_VALUE
56            ))
57        );
58    }
59}