1
- //! Rocket fairing to configure secure HTTP headers, such as content security policies
1
+ //! Rocket fairing to inject HTTP security headers, such as content security policies, into responses
2
2
3
3
use std:: io;
4
4
@@ -10,12 +10,14 @@ use rocket::http::Status;
10
10
use rocket:: { Data , Request , Response } ;
11
11
use tracing:: { Level , event} ;
12
12
13
+ // Configuration of Fairing
13
14
#[ derive( Clone ) ]
14
15
pub struct SecurityHttpHeaders {
15
16
pub config : crate :: configuration:: config:: CustomAppConfig ,
16
17
pub regex_paths : regex:: RegexSet ,
17
18
}
18
19
20
+ // Fairing implementation
19
21
#[ rocket:: async_trait]
20
22
impl Fairing for SecurityHttpHeaders {
21
23
fn info ( & self ) -> Info {
@@ -25,12 +27,27 @@ impl Fairing for SecurityHttpHeaders {
25
27
}
26
28
}
27
29
30
+ /// Executed on every request (we do not need it, but it is part of the Fairing trait)
31
+ ///
32
+ /// # Arguments
33
+ /// * `self` - Struct Security HTTP Headers
34
+ /// * `req` - Request object
35
+ ///
36
+ ///
28
37
async fn on_request ( & self , req : & mut Request < ' _ > , _: & mut Data < ' _ > ) {
29
38
// do nothing
30
39
}
31
40
41
+ /// Executed on every response. We inject here the HTTP Security Headers
42
+ ///
43
+ /// # Arguments
44
+ /// * `self` - Struct Security HTTP Headers
45
+ /// * `req` - Request object
46
+ /// * `res` - Response object
47
+ ///
32
48
async fn on_response < ' r > ( & self , req : & ' r Request < ' _ > , res : & mut Response < ' r > ) {
33
49
if ( res. status ( ) == Status :: Ok ) {
50
+ // Configure Content-Security Policy Header and insert nonces
34
51
let mut body_bytes = res. body_mut ( ) . to_bytes ( ) . await . unwrap ( ) ;
35
52
match self . config . clone ( ) . httpheaders . content_security_policy {
36
53
Some ( csp) => {
@@ -95,9 +112,48 @@ impl Fairing for SecurityHttpHeaders {
95
112
"Configuration: Content-Security-Policy: You did not specify a tag to inject a nonce"
96
113
) ,
97
114
}
98
-
99
115
res. set_raw_header ( "Content-Security-Policy" , csp_value) ;
100
116
res. set_sized_body ( body_bytes. len ( ) , io:: Cursor :: new ( body_bytes) ) ;
117
+ // Set other HTTP Security Headers
118
+ match self . config . clone ( ) . httpheaders . permissions_policy {
119
+ Some ( permissions_policy) => {
120
+ res. set_raw_header ( "Permissions-Policy" , permissions_policy) ;
121
+ }
122
+ None => ( ) ,
123
+ } ;
124
+ match self . config . clone ( ) . httpheaders . referrer_policy {
125
+ Some ( referrer_policy) => {
126
+ res. set_raw_header ( "Referrer-Policy" , referrer_policy) ;
127
+ }
128
+ None => ( ) ,
129
+ } ;
130
+ match self . config . clone ( ) . httpheaders . cross_origin_embedder_policy {
131
+ Some ( cross_origin_embedder_policy) => {
132
+ res. set_raw_header (
133
+ "Cross-Origin-Embedder-Policy" ,
134
+ cross_origin_embedder_policy,
135
+ ) ;
136
+ }
137
+ None => ( ) ,
138
+ } ;
139
+ match self . config . clone ( ) . httpheaders . cross_origin_opener_policy {
140
+ Some ( cross_origin_opener_policy) => {
141
+ res. set_raw_header (
142
+ "Cross-Origin-Opener-Policy" ,
143
+ cross_origin_opener_policy,
144
+ ) ;
145
+ }
146
+ None => ( ) ,
147
+ } ;
148
+ match self . config . clone ( ) . httpheaders . cross_origin_resource_policy {
149
+ Some ( cross_origin_resource_policy) => {
150
+ res. set_raw_header (
151
+ "Cross-Origin-Resource-Policy" ,
152
+ cross_origin_resource_policy,
153
+ ) ;
154
+ }
155
+ None => ( ) ,
156
+ } ;
101
157
}
102
158
}
103
159
None => ( ) ,
0 commit comments