static_web_server/
security_headers.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// This file is part of Static Web Server.
3// See https://static-web-server.net/ for more information
4// Copyright (C) 2019-present Jose Quintana <joseluisq.net>
5
6//! The module provides several HTTP security headers support.
7//!
8
9use http::header::{
10    CONTENT_SECURITY_POLICY, STRICT_TRANSPORT_SECURITY, X_CONTENT_TYPE_OPTIONS, X_FRAME_OPTIONS,
11};
12use hyper::{Body, Request, Response};
13
14use crate::{handler::RequestHandlerOpts, Error};
15
16pub(crate) fn init(enabled: bool, handler_opts: &mut RequestHandlerOpts) {
17    handler_opts.security_headers = enabled;
18    tracing::info!("security headers: enabled={enabled}");
19}
20
21/// Appends security headers to a response if necessary
22pub(crate) fn post_process<T>(
23    opts: &RequestHandlerOpts,
24    _req: &Request<T>,
25    mut resp: Response<Body>,
26) -> Result<Response<Body>, Error> {
27    if opts.security_headers {
28        append_headers(&mut resp);
29    }
30    Ok(resp)
31}
32
33/// It appends security headers like `Strict-Transport-Security: max-age=63072000; includeSubDomains; preload` (2 years max-age),
34///`X-Frame-Options: DENY` and `Content-Security-Policy: frame-ancestors 'self'`.
35pub fn append_headers(resp: &mut Response<Body>) {
36    // Strict-Transport-Security (HSTS)
37    resp.headers_mut().insert(
38        STRICT_TRANSPORT_SECURITY,
39        "max-age=63072000; includeSubDomains; preload"
40            .parse()
41            .unwrap(),
42    );
43
44    // X-Frame-Options
45    resp.headers_mut()
46        .insert(X_FRAME_OPTIONS, "DENY".parse().unwrap());
47
48    // X-Content-Type-Options
49    resp.headers_mut()
50        .insert(X_CONTENT_TYPE_OPTIONS, "nosniff".parse().unwrap());
51
52    // Content Security Policy (CSP)
53    resp.headers_mut().insert(
54        CONTENT_SECURITY_POLICY,
55        "frame-ancestors 'self'".parse().unwrap(),
56    );
57}