junobuild_storage/http/
headers.rs1use crate::constants::ASSET_ENCODING_NO_COMPRESSION;
2use crate::http::types::HeaderField;
3use crate::types::config::{StorageConfig, StorageConfigIFrame};
4use crate::types::store::{Asset, AssetEncoding, EncodingType};
5use crate::url::matching_urls;
6use hex::encode;
7
8pub fn build_headers(
9 asset: &Asset,
10 encoding: &AssetEncoding,
11 encoding_type: &EncodingType,
12 config: &StorageConfig,
13) -> Vec<HeaderField> {
14 let mut headers = asset.headers.clone();
15
16 headers.push(HeaderField(
18 "accept-ranges".to_string(),
19 "bytes".to_string(),
20 ));
21
22 headers.push(HeaderField(
23 "etag".to_string(),
24 format!("\"{}\"", encode(encoding.sha256)),
25 ));
26
27 headers.extend(security_headers());
29
30 if let Some(iframe_header) = iframe_headers(&config.unwrap_iframe()) {
32 headers.push(iframe_header);
33 }
34
35 if encoding_type.clone() != *ASSET_ENCODING_NO_COMPRESSION {
36 headers.push(HeaderField(
37 "Content-Encoding".to_string(),
38 encoding_type.to_string(),
39 ));
40 }
41
42 let config_headers = build_config_headers(&asset.key.full_path, config);
44 headers.extend(config_headers);
45
46 headers
47}
48
49pub fn build_redirect_headers(location: &str, iframe: &StorageConfigIFrame) -> Vec<HeaderField> {
50 let mut headers = Vec::new();
51
52 headers.extend(security_headers());
54
55 if let Some(iframe_header) = iframe_headers(iframe) {
57 headers.push(iframe_header);
58 }
59
60 headers.push(HeaderField("Location".to_string(), location.to_string()));
61
62 headers
63}
64
65fn security_headers() -> Vec<HeaderField> {
70 vec![
71 HeaderField("X-Content-Type-Options".to_string(), "nosniff".to_string()),
72 HeaderField(
73 "Strict-Transport-Security".to_string(),
74 "max-age=31536000 ; includeSubDomains".to_string(),
75 ),
76 HeaderField("Referrer-Policy".to_string(), "same-origin".to_string()),
79 ]
80}
81
82fn iframe_headers(iframe: &StorageConfigIFrame) -> Option<HeaderField> {
83 match iframe {
84 StorageConfigIFrame::Deny => Some(HeaderField(
85 "X-Frame-Options".to_string(),
86 "DENY".to_string(),
87 )),
88 StorageConfigIFrame::SameOrigin => Some(HeaderField(
89 "X-Frame-Options".to_string(),
90 "SAMEORIGIN".to_string(),
91 )),
92 StorageConfigIFrame::AllowAny => None,
93 }
94}
95
96pub fn build_config_headers(
97 requested_path: &str,
98 StorageConfig {
99 headers: config_headers,
100 ..
101 }: &StorageConfig,
102) -> Vec<HeaderField> {
103 matching_urls(requested_path, config_headers)
104 .iter()
105 .flat_map(|(_, headers)| headers.clone())
106 .collect()
107}