changesin headers

This commit is contained in:
Mateusz Gruszczyński
2026-08-02 11:04:04 +02:00
parent ede6d1de92
commit 464660a274
3 changed files with 47 additions and 36 deletions
+46 -18
View File
@@ -70,10 +70,6 @@ pub fn router(
.route("/icons/favicon-32.png", get(favicon_png))
.route("/icons/apple-touch-icon.png", get(apple_touch_icon))
.route("/f/{token}/{filename}", get(api::download_file))
.route(
"/files/{directory}/{filename}",
get(api::download_legacy_file),
)
.route("/api/auth/identity", post(auth::identity))
.route(
"/api/security/csrf",
@@ -245,7 +241,7 @@ async fn apply_response_header_policy(request: Request, next: Next) -> Response
fn apply_response_headers(policy: ResponseHeaderPolicy, headers: &mut HeaderMap) {
match policy {
ResponseHeaderPolicy::StaticAsset => {
ResponseHeaderPolicy::StaticAsset | ResponseHeaderPolicy::File => {
headers
.entry(header::X_CONTENT_TYPE_OPTIONS)
.or_insert(HeaderValue::from_static("nosniff"));
@@ -284,16 +280,23 @@ fn apply_response_headers(policy: ResponseHeaderPolicy, headers: &mut HeaderMap)
enum ResponseHeaderPolicy {
Application,
StaticAsset,
File,
}
fn response_header_policy(path: &str) -> ResponseHeaderPolicy {
if is_asset_path(path) || is_icon_path(path) {
if is_file_path(path) {
ResponseHeaderPolicy::File
} else if is_asset_path(path) || is_icon_path(path) {
ResponseHeaderPolicy::StaticAsset
} else {
ResponseHeaderPolicy::Application
}
}
fn is_file_path(path: &str) -> bool {
path == "/f" || path.starts_with("/f/")
}
fn is_asset_path(path: &str) -> bool {
path == "/assets" || path.starts_with("/assets/")
}
@@ -329,23 +332,21 @@ mod tests {
}
#[test]
fn keeps_file_routes_on_the_application_policy() {
for path in [
"/f",
"/f/token/image.png",
"/files",
"/files/legacy/image.png",
] {
assert_eq!(
response_header_policy(path),
ResponseHeaderPolicy::Application
);
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", "/unknown"] {
for path in [
"/",
"/api/auth/me",
"/static/missing.css",
"/files/legacy/image.png",
"/unknown",
] {
assert_eq!(
response_header_policy(path),
ResponseHeaderPolicy::Application
@@ -372,6 +373,33 @@ mod tests {
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();