Skip to main content

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, header::HeaderValue};
13
14use crate::{Error, handler::RequestHandlerOpts};
15
16// Pre-computed static header values to avoid per-response parsing
17static HSTS_VALUE: HeaderValue =
18    HeaderValue::from_static("max-age=63072000; includeSubDomains; preload");
19static XFO_VALUE: HeaderValue = HeaderValue::from_static("DENY");
20static XCTO_VALUE: HeaderValue = HeaderValue::from_static("nosniff");
21static CSP_VALUE: HeaderValue = HeaderValue::from_static("frame-ancestors 'self'");
22
23pub(crate) fn init(enabled: bool, handler_opts: &mut RequestHandlerOpts) {
24    handler_opts.security_headers = enabled;
25    tracing::info!("security headers: enabled={enabled}");
26}
27
28/// Appends security headers to a response if necessary
29pub(crate) fn post_process<T>(
30    opts: &RequestHandlerOpts,
31    _req: &Request<T>,
32    mut resp: Response<Body>,
33) -> Result<Response<Body>, Error> {
34    if opts.security_headers {
35        append_headers(&mut resp);
36    }
37    Ok(resp)
38}
39
40/// It appends security headers like `Strict-Transport-Security: max-age=63072000; includeSubDomains; preload` (2 years max-age),
41///`X-Frame-Options: DENY` and `Content-Security-Policy: frame-ancestors 'self'`.
42pub fn append_headers(resp: &mut Response<Body>) {
43    // Strict-Transport-Security (HSTS)
44    resp.headers_mut()
45        .insert(STRICT_TRANSPORT_SECURITY, HSTS_VALUE.clone());
46
47    // X-Frame-Options
48    resp.headers_mut()
49        .insert(X_FRAME_OPTIONS, XFO_VALUE.clone());
50
51    // X-Content-Type-Options
52    resp.headers_mut()
53        .insert(X_CONTENT_TYPE_OPTIONS, XCTO_VALUE.clone());
54
55    // Content Security Policy (CSP)
56    resp.headers_mut()
57        .insert(CONTENT_SECURITY_POLICY, CSP_VALUE.clone());
58}