diff --git a/CHANGELOG.md b/CHANGELOG.md index 2306217e12..85cca8cfc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,22 @@ ## DFX +### fix(frontend-canister): Allow overwriting default HTTP Headers for assets in frontend canister + +Allows to overwrite `Content-Type`, `Content-Encoding`, and `Cache-Control` HTTP headers with custom values via `.ic-assets.json5` config file. Example `.ic-assets.json5` file: +```json5 +[ + { + "match": "web-gz.data.gz", + "headers": { + "Content-Type": "application/octet-stream", + "Content-Encoding": "gzip" + } + } +] +``` +This change will trigger the update process for frontend canister (new module hash: `2ff0513123f11c57716d889ca487083fac7d94a4c9434d5879f8d0342ad9d759`). + ### fix: Save SNS canister IDs SNS canister IDs were not being parsed reliably. Now the candid file is being specified explicitly, which resolves the issue in at least some cases. @@ -501,6 +517,10 @@ Updated ic-ref to 0.0.1-1fba03ee - Module hash: b944b1e5533064d12e951621d5045d5291bcfd8cf9d60c28fef02c8fdb68e783 - https://github.com/dfinity/cycles-wallet/commit/fa86dd3a65b2509ca1e0c2bb9d7d4c5be95de378 +### Frontend canister: +- Module hash: 2ff0513123f11c57716d889ca487083fac7d94a4c9434d5879f8d0342ad9d759 +- https://github.com/dfinity/sdk/pull/2689 + # 0.11.2 ## DFX diff --git a/e2e/tests-dfx/assetscanister.bash b/e2e/tests-dfx/assetscanister.bash index e0bba0fed5..15e55becc6 100644 --- a/e2e/tests-dfx/assetscanister.bash +++ b/e2e/tests-dfx/assetscanister.bash @@ -506,3 +506,36 @@ CHERRIES" "$stdout" assert_match "HTTP/1.1 404 Not Found" } + +@test "asset configuration via .ic-assets.json5 - overwriting default headers" { + install_asset assetscanister + + dfx_start + + touch src/e2e_project_frontend/assets/thing.json + + echo '[ + { + "match": "thing.json", + "cache": { "max_age": 2000 }, + "headers": { + "Content-Encoding": "my-encoding", + "Content-Type": "x-type", + "Cache-Control": "custom", + "etag": "my-etag" + } + } + ]' > src/e2e_project_frontend/assets/.ic-assets.json5 + + dfx deploy + + ID=$(dfx canister id e2e_project_frontend) + PORT=$(get_webserver_port) + + assert_command curl --head "http://localhost:$PORT/thing.json?canisterId=$ID" + assert_match "cache-control: custom" + assert_match "content-encoding: my-encoding" + assert_match "content-type: x-type" + assert_not_match "etag: my-etag" + assert_match "etag: \"[a-z0-9]{64}\"" +} diff --git a/src/canisters/frontend/ic-certified-assets/src/state_machine.rs b/src/canisters/frontend/ic-certified-assets/src/state_machine.rs index 8ca272ac81..d69faab4cd 100644 --- a/src/canisters/frontend/ic-certified-assets/src/state_machine.rs +++ b/src/canisters/frontend/ic-certified-assets/src/state_machine.rs @@ -709,19 +709,19 @@ fn build_ok( callback: Func, etags: Vec, ) -> HttpResponse { - let mut headers = vec![("Content-Type".to_string(), asset.content_type.to_string())]; + let mut headers = HashMap::from([("content-type".to_string(), asset.content_type.to_string())]); if enc_name != "identity" { - headers.push(("Content-Encoding".to_string(), enc_name.to_string())); + headers.insert("content-encoding".to_string(), enc_name.to_string()); } if let Some(head) = certificate_header { - headers.push(head); + headers.insert(head.0, head.1); } if let Some(max_age) = asset.max_age { - headers.push(("Cache-Control".to_string(), format!("max-age={}", max_age))); + headers.insert("cache-control".to_string(), format!("max-age={}", max_age)); } if let Some(arg_headers) = asset.headers.as_ref() { for (k, v) in arg_headers { - headers.push((k.to_owned(), v.to_owned())); + headers.insert(k.to_owned().to_lowercase(), v.to_owned()); } } @@ -731,16 +731,16 @@ fn build_ok( let (status_code, body) = if etags.contains(&enc.sha256) { (304, RcBytes::default()) } else { - headers.push(( - "ETag".to_string(), + headers.insert( + "etag".to_string(), format!("\"{}\"", hex::encode(enc.sha256)), - )); + ); (200, enc.content_chunks[chunk_index].clone()) }; HttpResponse { status_code, - headers, + headers: headers.into_iter().collect::<_>(), body, streaming_strategy, } diff --git a/src/distributed/assetstorage.wasm.gz b/src/distributed/assetstorage.wasm.gz old mode 100755 new mode 100644 index 54aedf8705..6b8291ea40 Binary files a/src/distributed/assetstorage.wasm.gz and b/src/distributed/assetstorage.wasm.gz differ