Skip to main content

systemprompt_api/services/middleware/
security_headers.rs

1use axum::extract::Request;
2use axum::http::HeaderValue;
3use axum::middleware::Next;
4use axum::response::Response;
5use systemprompt_extension::FrameOptionsOverride;
6use systemprompt_models::profile::SecurityHeadersConfig;
7
8pub async fn inject_security_headers(
9    config: SecurityHeadersConfig,
10    request: Request,
11    next: Next,
12) -> Response {
13    let mut response = next.run(request).await;
14    let frame_override = response.extensions().get::<FrameOptionsOverride>().copied();
15    let headers = response.headers_mut();
16
17    if let Ok(value) = HeaderValue::from_str(&config.hsts) {
18        headers.insert("strict-transport-security", value);
19    }
20
21    if let Some(FrameOptionsOverride(frame_options)) = frame_override {
22        match frame_options.header_value() {
23            Some(value) => {
24                headers.insert("x-frame-options", HeaderValue::from_static(value));
25            },
26            None => {
27                headers.remove("x-frame-options");
28            },
29        }
30        if let Ok(value) = HeaderValue::from_str(&format!(
31            "frame-ancestors {}",
32            frame_options.frame_ancestors()
33        )) {
34            headers.insert("content-security-policy", value);
35        }
36    } else if let Ok(value) = HeaderValue::from_str(&config.frame_options) {
37        headers.insert("x-frame-options", value);
38    }
39
40    if let Ok(value) = HeaderValue::from_str(&config.content_type_options) {
41        headers.insert("x-content-type-options", value);
42    }
43
44    if let Ok(value) = HeaderValue::from_str(&config.referrer_policy) {
45        headers.insert("referrer-policy", value);
46    }
47
48    if let Ok(value) = HeaderValue::from_str(&config.permissions_policy) {
49        headers.insert("permissions-policy", value);
50    }
51
52    if let Some(ref csp) = config.content_security_policy
53        && frame_override.is_none()
54        && let Ok(value) = HeaderValue::from_str(csp)
55    {
56        headers.insert("content-security-policy", value);
57    }
58
59    response
60}