From d9a57803394f9e02e038508cd756cb510d14d807 Mon Sep 17 00:00:00 2001 From: Adam Spofford Date: Fri, 6 Dec 2024 14:25:59 -0800 Subject: [PATCH 1/2] Fix json escaping in header values --- e2e/tests-dfx/assetscanister.bash | 21 +++++++++++++ .../frontend/ic-asset/src/asset/config.rs | 31 ++++++++++++++----- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/e2e/tests-dfx/assetscanister.bash b/e2e/tests-dfx/assetscanister.bash index d92f26758b..0392aa97e6 100644 --- a/e2e/tests-dfx/assetscanister.bash +++ b/e2e/tests-dfx/assetscanister.bash @@ -1897,6 +1897,27 @@ WARN: { assert_match '/somedir/upload-me.txt 1/1 \(8 bytes\) sha [0-9a-z]* \(with cache and 1 header\)' } +@test "asset configuration via .ic-assets.json5 - respects weird characters" { + install_asset assetscanister + touch src/e2e_project_frontend/assets/thing.txt + cat <<'EOF' >src/e2e_project_frontend/assets/.ic-assets.json5 +[ + { + "match": "thing.txt", + "headers": { + "X-Dummy-Header": "\"\'@%({[~$?\\" + } + } +] +EOF + dfx_start + assert_command dfx deploy + ID=$(dfx canister id e2e_project_frontend) + PORT=$(get_webserver_port) + assert_command curl --head "http://localhost:$PORT/thing.txt?canisterId=$ID" + assert_contains 'x-dummy-header: "'"'"'@%({[~$?\' +} + @test "uses selected canister wasm" { dfx_start use_asset_wasm 0.12.1 diff --git a/src/canisters/frontend/ic-asset/src/asset/config.rs b/src/canisters/frontend/ic-asset/src/asset/config.rs index 924f9e43e9..9eb4995da0 100644 --- a/src/canisters/frontend/ic-asset/src/asset/config.rs +++ b/src/canisters/frontend/ic-asset/src/asset/config.rs @@ -337,7 +337,7 @@ mod rule_utils { use crate::error::LoadRuleError; use globset::{Glob, GlobMatcher}; use itertools::Itertools; - use serde::{Deserialize, Serializer}; + use serde::{de::Error as _, Deserialize, Serializer}; use serde_json::Value; use std::collections::BTreeMap; use std::fmt; @@ -387,12 +387,29 @@ mod rule_utils { where D: serde::Deserializer<'de>, { - match serde_json::value::Value::deserialize(deserializer)? { - Value::Object(v) => Ok(Maybe::Value( - v.into_iter() - .map(|(k, v)| (k, v.to_string().trim_matches('"').to_string())) - .collect::>(), - )), + match Value::deserialize(deserializer)? { + Value::Object(v) => { + Ok(Maybe::Value( + v.into_iter() + .map(|(k, v)| { + Ok(( + k, + match v { + Value::Bool(b) => b.to_string(), + Value::Number(n) => n.to_string(), + Value::String(s) => s, // v.to_string() would json-escape this + Value::Null => String::new(), + v => { + return Err(D::Error::custom(format!( + "headers must be strings, numbers, or bools (was {v:?})" + ))) + } + }, + )) + }) + .collect::, D::Error>>()?, + )) + } Value::Null => Ok(Maybe::Null), _ => Err(serde::de::Error::custom( "wrong data format for field `headers` (only map or null are allowed)", From 23a6647a731a1ed217f7f0c1c8ce74f52670f74d Mon Sep 17 00:00:00 2001 From: Adam Spofford Date: Fri, 6 Dec 2024 14:32:31 -0800 Subject: [PATCH 2/2] shellcheck --- e2e/tests-dfx/assetscanister.bash | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e/tests-dfx/assetscanister.bash b/e2e/tests-dfx/assetscanister.bash index 0392aa97e6..e2b027eaae 100644 --- a/e2e/tests-dfx/assetscanister.bash +++ b/e2e/tests-dfx/assetscanister.bash @@ -1915,6 +1915,7 @@ EOF ID=$(dfx canister id e2e_project_frontend) PORT=$(get_webserver_port) assert_command curl --head "http://localhost:$PORT/thing.txt?canisterId=$ID" + # shellcheck disable=SC1003 assert_contains 'x-dummy-header: "'"'"'@%({[~$?\' }