Skip to content
This repository was archived by the owner on Nov 28, 2024. It is now read-only.

Commit fbfd60c

Browse files
committed
fix content disposition header
1 parent 6b076bc commit fbfd60c

2 files changed

Lines changed: 28 additions & 5 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ serde = "1.0.147"
2424
serde_derive = "1.0.147"
2525
once_cell = "1.10"
2626
async-compression = { version = "0.3.15", features = ["tokio", "brotli", "gzip", "deflate"] }
27+
regex = "1"

src/routes.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
use std::path::Path;
2+
13
use bytes::Bytes;
24
use image::ImageFormat;
35
use log::info;
6+
use regex::Regex;
47
use tokio::task;
58
use unicase::Ascii;
69
use warp::{Filter, http, Rejection};
@@ -49,7 +52,7 @@ async fn proxy_upscale_and_forward(
4952
headers: HeaderMap,
5053
body: Bytes,
5154
) -> Result<Response<Body>, Rejection> {
52-
let uri_str = format!("{} {}", method, uri.as_str());
55+
let uri_str = format!("{} {}{}", method, uri.as_str(), params.as_deref().map(|query| "?".to_string() + query).unwrap_or_default());
5356
// TODO do not request compressed data to avoid decode and re-encode
5457
let response = proxy_to_and_forward_response(proxy_address, base_path, uri, params, method, headers, body).await?;
5558
let status = response.status();
@@ -104,17 +107,26 @@ async fn response_to_upscaled_reply(
104107
format: ImageFormat,
105108
) -> Result<Response<Body>, errors::Error> {
106109
let mime_type = match format {
107-
ImageFormat::Png => { Some("image/png") }
108-
ImageFormat::Jpeg => { Some("image/jpeg") }
109-
ImageFormat::WebP => { Some("image/webp") }
110+
ImageFormat::Png => { Some(("image/png", "png")) }
111+
ImageFormat::Jpeg => { Some(("image/jpeg", "jpeg")) }
112+
ImageFormat::WebP => { Some(("image/webp", "webp")) }
110113
_ => { None }
111114
};
112115
let mut builder = http::Response::builder();
113116
for (k, v) in headers {
114117
if Ascii::new("Content-Length") == k {
115118
builder = builder.header("Content-Length", bytes.len())
116119
} else if Ascii::new("Content-Type") == k && mime_type.is_some() {
117-
builder = builder.header("Content-Type", mime_type.unwrap())
120+
builder = builder.header("Content-Type", mime_type.unwrap().0)
121+
} else if Ascii::new("Content-Disposition") == k && mime_type.is_some() {
122+
let new_value: String = v.to_str().unwrap().split("; ")
123+
.map(|param| if param.starts_with("filename=") {
124+
with_new_file_extension(param, mime_type.unwrap().1)
125+
} else if param.starts_with("filename*=") {
126+
with_new_file_extension(param, mime_type.unwrap().1)
127+
} else { param.to_string() })
128+
.collect::<Vec<String>>().join("; ");
129+
builder = builder.header("Content-Disposition", new_value)
118130
} else {
119131
builder = builder.header(k, v);
120132
}
@@ -125,6 +137,16 @@ async fn response_to_upscaled_reply(
125137
.map_err(errors::Error::Http)
126138
}
127139

140+
fn with_new_file_extension(name: &str, extension: &str) -> String {
141+
let regex = Regex::new(r"(filename\*=UTF-8''|filename=)(.+\b)").unwrap();
142+
let captures = regex.captures(name).unwrap();
143+
let param_name = captures.get(1).unwrap().as_str();
144+
let filename = captures.get(2).unwrap().as_str();
145+
let new_filename = Path::new(filename).with_extension(extension)
146+
.into_os_string().into_string().unwrap();
147+
format!("{}{}", param_name, new_filename)
148+
}
149+
128150
fn unwrap_encoding_header(encoding: &HeaderValue) -> Algorithm {
129151
let encoding = encoding.to_str().unwrap();
130152
match encoding {

0 commit comments

Comments
 (0)