From d492fb0eac8296513f003cf32edf80ec99bf8f2b Mon Sep 17 00:00:00 2001 From: Jae-Heon Ji <32578710+jaeheonji@users.noreply.github.com> Date: Thu, 10 Dec 2020 00:48:06 +0900 Subject: [PATCH] fix(op_crates/fetch): support non-ascii response headers value (#8600) --- cli/tests/unit/fetch_test.ts | 14 ++++++++++++++ op_crates/fetch/lib.rs | 15 ++++++++++++++- test_util/src/lib.rs | 13 ++++++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/cli/tests/unit/fetch_test.ts b/cli/tests/unit/fetch_test.ts index 99b7531a3e..6a5cff164f 100644 --- a/cli/tests/unit/fetch_test.ts +++ b/cli/tests/unit/fetch_test.ts @@ -685,6 +685,20 @@ unitTest( }, ); +unitTest( + { + perms: { net: true }, + }, + async function fetchWithNonAsciiRedirection(): Promise { + const response = await fetch("http://localhost:4545/non_ascii_redirect", { + redirect: "manual", + }); + assertEquals(response.status, 301); + assertEquals(response.headers.get("location"), "/redirect®"); + await response.text(); + }, +); + unitTest( { perms: { net: true }, diff --git a/op_crates/fetch/lib.rs b/op_crates/fetch/lib.rs index 49d951d8f4..8a4c1ee169 100644 --- a/op_crates/fetch/lib.rs +++ b/op_crates/fetch/lib.rs @@ -156,7 +156,20 @@ where let status = res.status(); let mut res_headers = Vec::new(); for (key, val) in res.headers().iter() { - res_headers.push((key.to_string(), val.to_str().unwrap().to_owned())); + let key_string = key.to_string(); + + if val.as_bytes().is_ascii() { + res_headers.push((key_string, val.to_str().unwrap().to_owned())) + } else { + res_headers.push(( + key_string, + val + .as_bytes() + .iter() + .map(|&c| c as char) + .collect::(), + )); + } } let rid = state diff --git a/test_util/src/lib.rs b/test_util/src/lib.rs index a455814913..8a47eb139c 100644 --- a/test_util/src/lib.rs +++ b/test_util/src/lib.rs @@ -290,6 +290,16 @@ pub async fn run_all_servers() { *res.status_mut() = StatusCode::FOUND; Box::new(res) }); + let non_ascii_redirect = + warp::path("non_ascii_redirect").map(|| -> Box { + let mut res = Response::new(Body::empty()); + *res.status_mut() = StatusCode::MOVED_PERMANENTLY; + res.headers_mut().insert( + "location", + HeaderValue::from_bytes(b"/redirect\xae").unwrap(), + ); + Box::new(res) + }); let etag_script = warp::path!("etag_script.ts") .and(warp::header::optional::("if-none-match")) @@ -444,7 +454,8 @@ pub async fn run_all_servers() { .or(echo_server) .or(echo_multipart_file) .or(multipart_form_data) - .or(bad_redirect); + .or(bad_redirect) + .or(non_ascii_redirect); let http_fut = warp::serve(content_type_handler.clone()).bind(([127, 0, 0, 1], PORT));