gotham/middleware/
security.rs

1//! Security based middleware to handle security based sanitizations.
2//!
3//! Prior to v0.3, this middleware was baked into responses by default. It has
4//! now been separated to allow optional usage. You can attach as a middleware
5//! at startup to include behaviour as was present before.
6//!
7//! Currently this middleware will set the following headers:
8//!
9//! - X-CONTENT-TYPE-OPTIONS: "nosniff"
10//! - X-FRAME-OPTIONS: "DENY"
11//! - X-XSS-PROTECTION: "1; mode=block"
12//!
13//! More may be added in future, but these headers provide compatibility with
14//! previous versions of Gotham.
15use crate::handler::HandlerFuture;
16use crate::middleware::{Middleware, NewMiddleware};
17use crate::state::State;
18
19use futures_util::future::{self, FutureExt, TryFutureExt};
20use hyper::header::{HeaderValue, X_CONTENT_TYPE_OPTIONS, X_FRAME_OPTIONS, X_XSS_PROTECTION};
21use std::pin::Pin;
22
23// constant strings to be used as header values
24const XFO_VALUE: &str = "DENY";
25const XXP_VALUE: &str = "1; mode=block";
26const XCTO_VALUE: &str = "nosniff";
27
28/// Middleware binding for the Gotham security handlers.
29///
30/// This acts as nothing more than a trait implementation for the time
31/// being; there are no fields on the struct in use (yet).
32#[derive(Clone)]
33pub struct SecurityMiddleware;
34
35/// `Middleware` trait implementation.
36impl Middleware for SecurityMiddleware {
37    /// Attaches security headers to the response.
38    fn call<Chain>(self, state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
39    where
40        Chain: FnOnce(State) -> Pin<Box<HandlerFuture>>,
41    {
42        let f = chain(state).and_then(|(state, mut response)| {
43            {
44                let headers = response.headers_mut();
45
46                headers.insert(X_FRAME_OPTIONS, HeaderValue::from_static(XFO_VALUE));
47                headers.insert(X_XSS_PROTECTION, HeaderValue::from_static(XXP_VALUE));
48                headers.insert(X_CONTENT_TYPE_OPTIONS, HeaderValue::from_static(XCTO_VALUE));
49            }
50            future::ok((state, response))
51        });
52
53        f.boxed()
54    }
55}
56
57/// `NewMiddleware` trait implementation.
58impl NewMiddleware for SecurityMiddleware {
59    type Instance = Self;
60
61    /// Clones the current middleware to a new instance.
62    fn new_middleware(&self) -> anyhow::Result<Self::Instance> {
63        Ok(self.clone())
64    }
65}