Skip to main content

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.
17pub fn default_headers() -> DefaultHeaders {
18    DefaultHeaders::new()
19        .add(("X-Frame-Options", X_FRAME_OPTIONS_VALUE))
20        .add(("Referrer-Policy", REFERRER_POLICY_VALUE))
21        .add(("X-Content-Type-Options", X_CONTENT_TYPE_OPTIONS_VALUE))
22}
23
24#[cfg(test)]
25mod tests {
26    use super::{
27        REFERRER_POLICY_VALUE, X_CONTENT_TYPE_OPTIONS_VALUE, X_FRAME_OPTIONS_VALUE, default_headers,
28    };
29    use actix_web::{HttpResponse, http::header, test, web};
30
31    #[actix_web::test]
32    async fn default_headers_adds_security_headers() {
33        let app = test::init_service(
34            actix_web::App::new()
35                .wrap(default_headers())
36                .route("/", web::get().to(HttpResponse::Ok)),
37        )
38        .await;
39
40        let request = test::TestRequest::get().uri("/").to_request();
41        let response = test::call_service(&app, request).await;
42
43        assert_eq!(
44            response.headers().get("x-frame-options"),
45            Some(&header::HeaderValue::from_static(X_FRAME_OPTIONS_VALUE))
46        );
47        assert_eq!(
48            response.headers().get("referrer-policy"),
49            Some(&header::HeaderValue::from_static(REFERRER_POLICY_VALUE))
50        );
51        assert_eq!(
52            response.headers().get("x-content-type-options"),
53            Some(&header::HeaderValue::from_static(
54                X_CONTENT_TYPE_OPTIONS_VALUE
55            ))
56        );
57    }
58}