systemprompt_api/services/middleware/
security_headers.rs1use 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}