122 lines
3.7 KiB
Rust
122 lines
3.7 KiB
Rust
/*
|
|
* Copyright (C) 2026 Mateusz Gruszczyński @linuxiarz.pl
|
|
* Source-Available Code / Dual-Licensed.
|
|
*
|
|
* Free for non-commercial and evaluation use under terms of BSL/GPLv3.
|
|
* Commercial or production use requires a valid paid license.
|
|
* See LICENSE file in repository root for details.
|
|
*/
|
|
|
|
use super::{ResponseHeaderPolicy, apply_response_headers, response_header_policy};
|
|
use axum::http::{HeaderMap, HeaderValue, header};
|
|
|
|
#[test]
|
|
fn classifies_assets_and_icons_as_static_assets() {
|
|
for path in [
|
|
"/assets/app.js",
|
|
"/assets",
|
|
"/favicon.ico",
|
|
"/icons/favicon.svg",
|
|
"/icons/missing.svg",
|
|
] {
|
|
assert_eq!(
|
|
response_header_policy(path),
|
|
ResponseHeaderPolicy::StaticAsset
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn classifies_file_routes_as_files() {
|
|
for path in ["/f", "/f/token/image.png"] {
|
|
assert_eq!(response_header_policy(path), ResponseHeaderPolicy::File);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn classifies_other_routes_as_application() {
|
|
for path in [
|
|
"/",
|
|
"/api/auth/me",
|
|
"/static/missing.css",
|
|
"/files/legacy/image.png",
|
|
"/unknown",
|
|
] {
|
|
assert_eq!(
|
|
response_header_policy(path),
|
|
ResponseHeaderPolicy::Application
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn static_asset_policy_only_adds_nosniff() {
|
|
let mut headers = HeaderMap::new();
|
|
headers.insert(
|
|
header::CACHE_CONTROL,
|
|
HeaderValue::from_static("public, max-age=3600"),
|
|
);
|
|
|
|
apply_response_headers(ResponseHeaderPolicy::StaticAsset, &mut headers);
|
|
|
|
assert_eq!(headers.len(), 2);
|
|
assert_eq!(headers[header::X_CONTENT_TYPE_OPTIONS], "nosniff");
|
|
assert!(!headers.contains_key("x-frame-options"));
|
|
assert!(!headers.contains_key("cross-origin-opener-policy"));
|
|
assert!(!headers.contains_key("cross-origin-resource-policy"));
|
|
assert!(!headers.contains_key("referrer-policy"));
|
|
assert!(!headers.contains_key("permissions-policy"));
|
|
}
|
|
|
|
#[test]
|
|
fn file_policy_keeps_file_headers_without_document_policies() {
|
|
let mut headers = HeaderMap::new();
|
|
headers.insert(
|
|
"content-security-policy",
|
|
HeaderValue::from_static("default-src 'none'; sandbox"),
|
|
);
|
|
headers.insert(
|
|
header::CONTENT_DISPOSITION,
|
|
HeaderValue::from_static("attachment; filename=\"manual.pdf\""),
|
|
);
|
|
|
|
apply_response_headers(ResponseHeaderPolicy::File, &mut headers);
|
|
|
|
assert_eq!(headers[header::X_CONTENT_TYPE_OPTIONS], "nosniff");
|
|
assert_eq!(
|
|
headers["content-security-policy"],
|
|
"default-src 'none'; sandbox"
|
|
);
|
|
assert!(headers.contains_key(header::CONTENT_DISPOSITION));
|
|
assert!(!headers.contains_key("x-frame-options"));
|
|
assert!(!headers.contains_key("cross-origin-opener-policy"));
|
|
assert!(!headers.contains_key("cross-origin-resource-policy"));
|
|
assert!(!headers.contains_key("referrer-policy"));
|
|
assert!(!headers.contains_key("permissions-policy"));
|
|
}
|
|
|
|
#[test]
|
|
fn application_policy_preserves_handler_headers() {
|
|
let mut headers = HeaderMap::new();
|
|
headers.insert(
|
|
"content-security-policy",
|
|
HeaderValue::from_static("default-src 'none'; sandbox"),
|
|
);
|
|
|
|
apply_response_headers(ResponseHeaderPolicy::Application, &mut headers);
|
|
|
|
assert_eq!(
|
|
headers["content-security-policy"],
|
|
"default-src 'none'; sandbox"
|
|
);
|
|
assert_eq!(headers["x-frame-options"], "DENY");
|
|
assert_eq!(headers["cross-origin-opener-policy"], "same-origin");
|
|
assert_eq!(headers["cross-origin-resource-policy"], "same-origin");
|
|
assert_eq!(headers[header::X_CONTENT_TYPE_OPTIONS], "nosniff");
|
|
assert_eq!(
|
|
headers["referrer-policy"],
|
|
"strict-origin-when-cross-origin"
|
|
);
|
|
assert!(headers.contains_key("permissions-policy"));
|
|
}
|