changesin headers
This commit is contained in:
@@ -524,23 +524,6 @@ pub async fn download_file(
|
||||
serve_token_file(&state, &token, &filename).await
|
||||
}
|
||||
|
||||
pub async fn download_legacy_file(
|
||||
State(state): State<SharedState>,
|
||||
Path((directory, filename)): Path<(String, String)>,
|
||||
) -> Result<Response, ApiError> {
|
||||
let Some((id_part, token)) = directory.split_once('_') else {
|
||||
return Err(ApiError::not_found_file());
|
||||
};
|
||||
let id: i64 = id_part.parse().map_err(|_| ApiError::not_found_file())?;
|
||||
let owner = db::find_file_owner(&state.db, token)
|
||||
.await?
|
||||
.ok_or_else(ApiError::not_found_file)?;
|
||||
if owner.id != id {
|
||||
return Err(ApiError::not_found_file());
|
||||
}
|
||||
serve_token_file(&state, token, &filename).await
|
||||
}
|
||||
|
||||
async fn serve_token_file(
|
||||
state: &SharedState,
|
||||
token: &str,
|
||||
|
||||
+46
-18
@@ -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();
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ pub(super) async fn apple_touch_icon() -> Response {
|
||||
}
|
||||
|
||||
pub(super) async fn robots_txt() -> Response {
|
||||
let mut response = "User-agent: *\nDisallow: /f/\nDisallow: /files/\n".into_response();
|
||||
let mut response = "User-agent: *\nDisallow: /f/\n".into_response();
|
||||
response.headers_mut().insert(
|
||||
header::CONTENT_TYPE,
|
||||
HeaderValue::from_static("text/plain; charset=utf-8"),
|
||||
|
||||
Reference in New Issue
Block a user