lemon/handlers/
security_wrappers.rs1use async_trait::async_trait;
2use hyper::http::header;
3use std::sync::Arc;
4
5use crate::{
6 common,
7 config::SecurityConfig,
8 handlers::{BoxedBody, Handler},
9};
10use hyper::body::Incoming as IncomingBody;
11use hyper::{Request, Response};
12
13pub struct SecHeaders<H> {
14 inner: H,
15 cfg: Arc<SecurityConfig>,
16 hsts_value: Option<header::HeaderValue>,
17}
18
19impl<H> SecHeaders<H> {
20 pub fn new(inner: H, cfg: Arc<SecurityConfig>, is_https: bool) -> Self {
21 let hsts_value = if is_https && cfg.add_default_headers != Some(false) {
22 Some(common::build_hsts(&cfg))
23 } else {
24 None
25 };
26 Self {
27 inner,
28 cfg,
29 hsts_value,
30 }
31 }
32}
33
34#[async_trait]
35impl<H: Handler> Handler for SecHeaders<H> {
36 async fn handle(&self, req: Request<IncomingBody>) -> anyhow::Result<Response<BoxedBody>> {
37 let mut resp = self.inner.handle(req).await?;
38
39 let hdrs = resp.headers_mut();
40
41 hdrs.entry(common::H_XCTO)
43 .or_insert(common::V_NOSNIFF.clone());
44
45 match self.cfg.frame_options.as_deref() {
47 Some("SAMEORIGIN") => {
48 hdrs.entry(common::H_XFO)
49 .or_insert(common::V_SAMEORIGIN.clone());
50 }
51 Some("NONE") => { }
52 _ => {
53 hdrs.entry(common::H_XFO).or_insert(common::V_DENY.clone());
54 }
55 }
56
57 if let Some(hsts_header_value) = &self.hsts_value {
59 hdrs.entry(header::STRICT_TRANSPORT_SECURITY)
60 .or_insert_with(|| hsts_header_value.clone());
61 }
62
63 Ok(resp)
64 }
65}