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