Skip to content

Commit 5332235

Browse files
author
Marcin Nowak-Liebiediew
authored
fix(frontend-canister): allow overwriting default HTTP headers (#2689)
Change to use HashMap instead of Vec to aggregate HTTP Headers, and also cast all HTTP Header keys lowercase. This change required an updating asset canister wasm.
1 parent 9aa0060 commit 5332235

4 files changed

Lines changed: 62 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@
44

55
## DFX
66

7+
### fix(frontend-canister): Allow overwriting default HTTP Headers for assets in frontend canister
8+
9+
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:
10+
```json5
11+
[
12+
{
13+
"match": "web-gz.data.gz",
14+
"headers": {
15+
"Content-Type": "application/octet-stream",
16+
"Content-Encoding": "gzip"
17+
}
18+
}
19+
]
20+
```
21+
This change will trigger the update process for frontend canister (new module hash: `2ff0513123f11c57716d889ca487083fac7d94a4c9434d5879f8d0342ad9d759`).
22+
723
### fix: Save SNS canister IDs
824

925
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
501517
- Module hash: b944b1e5533064d12e951621d5045d5291bcfd8cf9d60c28fef02c8fdb68e783
502518
- https://github.com/dfinity/cycles-wallet/commit/fa86dd3a65b2509ca1e0c2bb9d7d4c5be95de378
503519
520+
### Frontend canister:
521+
- Module hash: 2ff0513123f11c57716d889ca487083fac7d94a4c9434d5879f8d0342ad9d759
522+
- https://github.com/dfinity/sdk/pull/2689
523+
504524
# 0.11.2
505525
506526
## DFX

e2e/tests-dfx/assetscanister.bash

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,3 +506,36 @@ CHERRIES" "$stdout"
506506
assert_match "HTTP/1.1 404 Not Found"
507507

508508
}
509+
510+
@test "asset configuration via .ic-assets.json5 - overwriting default headers" {
511+
install_asset assetscanister
512+
513+
dfx_start
514+
515+
touch src/e2e_project_frontend/assets/thing.json
516+
517+
echo '[
518+
{
519+
"match": "thing.json",
520+
"cache": { "max_age": 2000 },
521+
"headers": {
522+
"Content-Encoding": "my-encoding",
523+
"Content-Type": "x-type",
524+
"Cache-Control": "custom",
525+
"etag": "my-etag"
526+
}
527+
}
528+
]' > src/e2e_project_frontend/assets/.ic-assets.json5
529+
530+
dfx deploy
531+
532+
ID=$(dfx canister id e2e_project_frontend)
533+
PORT=$(get_webserver_port)
534+
535+
assert_command curl --head "http://localhost:$PORT/thing.json?canisterId=$ID"
536+
assert_match "cache-control: custom"
537+
assert_match "content-encoding: my-encoding"
538+
assert_match "content-type: x-type"
539+
assert_not_match "etag: my-etag"
540+
assert_match "etag: \"[a-z0-9]{64}\""
541+
}

src/canisters/frontend/ic-certified-assets/src/state_machine.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -709,19 +709,19 @@ fn build_ok(
709709
callback: Func,
710710
etags: Vec<Hash>,
711711
) -> HttpResponse {
712-
let mut headers = vec![("Content-Type".to_string(), asset.content_type.to_string())];
712+
let mut headers = HashMap::from([("content-type".to_string(), asset.content_type.to_string())]);
713713
if enc_name != "identity" {
714-
headers.push(("Content-Encoding".to_string(), enc_name.to_string()));
714+
headers.insert("content-encoding".to_string(), enc_name.to_string());
715715
}
716716
if let Some(head) = certificate_header {
717-
headers.push(head);
717+
headers.insert(head.0, head.1);
718718
}
719719
if let Some(max_age) = asset.max_age {
720-
headers.push(("Cache-Control".to_string(), format!("max-age={}", max_age)));
720+
headers.insert("cache-control".to_string(), format!("max-age={}", max_age));
721721
}
722722
if let Some(arg_headers) = asset.headers.as_ref() {
723723
for (k, v) in arg_headers {
724-
headers.push((k.to_owned(), v.to_owned()));
724+
headers.insert(k.to_owned().to_lowercase(), v.to_owned());
725725
}
726726
}
727727

@@ -731,16 +731,16 @@ fn build_ok(
731731
let (status_code, body) = if etags.contains(&enc.sha256) {
732732
(304, RcBytes::default())
733733
} else {
734-
headers.push((
735-
"ETag".to_string(),
734+
headers.insert(
735+
"etag".to_string(),
736736
format!("\"{}\"", hex::encode(enc.sha256)),
737-
));
737+
);
738738
(200, enc.content_chunks[chunk_index].clone())
739739
};
740740

741741
HttpResponse {
742742
status_code,
743-
headers,
743+
headers: headers.into_iter().collect::<_>(),
744744
body,
745745
streaming_strategy,
746746
}

src/distributed/assetstorage.wasm.gz

100755100644
1.17 KB
Binary file not shown.

0 commit comments

Comments
 (0)