Gwojda
January 23, 2026, 1:33pm
1
Hey,
I’m facing right now with an issue with range header, (i used a random pictures i had, >2Mb here : https://4lfpx-eqaaa-aaaag-aujna-cai.raw.icp0.io/icrc3.png ) for example, it was working before but for some reason it looks like the ic gateway is returning bad stuff on the range header.
curl -I "https://4lfpx-eqaaa-aaaag-aujna-cai.raw.icp0.io/icrc3.png" 2>&1
HTTP/2 200
content-length: 2000000
curl: (16) Invalid HTTP header field was received: frame type: 1, stream: 1, name: [content-length], value: [2535142]
We receive 2 content-length header, one wrong and one correct.
Can you help here?
Note that locally, it seems to work correctly according to what i heard.
1 Like
Hey @Gwojda ,
I see the two headers you are mentioning:
(1) Set by the canister
content-length
2000000
(2) Set by the HTTP gateway
content-length
2535142
But to dig deeper, I need to understand better what you are doing. You are writing a canister that returns streaming response (partial assets with range headers), right? You set the content-length.
Gwojda
January 23, 2026, 2:27pm
3
Thanks. It’s a storage canister that serve asset on http endpoint. you can check here : ic-storage-canister/canister/src at master · BitySA/ic-storage-canister · GitHub and here for how assets are served : ic-storage-canister/canister/src/queries/http_request.rs at master · BitySA/ic-storage-canister · GitHub . I’m 99% sure it was working before, i’m pretty sure i tested like few months ago with a big videos and a big pictures. No update on ic-asset libs btw since a long time.
Gwojda
January 28, 2026, 2:08pm
4
any updates? Thanks Thanks
Gwojda
February 11, 2026, 7:57am
5
Hey @rbirkner ,
Any update here ? I saw some new update has been done here, but it’s looks like the issue is still there, even after update on my side.
I just use ic-asset-certification, so if the issue is on canister side, i guess it’s related with an error here
// ),
// }
];
asset_configs
}
pub fn certify_asset(assets: Vec<Asset<'static, '_>>) {
let asset_configs = get_asset_config();
ASSET_ROUTER.with_borrow_mut(|asset_router| {
// 4. Certify the assets using the `certify_assets` function from the `ic-asset-certification` crate.
if let Err(err) = asset_router.certify_assets(assets.clone(), asset_configs) {
ic_cdk::trap(&format!("Failed to certify assets: {}", err));
}
// 5. Set the canister's certified data.
certified_data_set(&asset_router.root_hash());
});
}
#[query(hidden = true)]
async fn http_request(req: HttpRequest<'static>) -> HttpResponse<'static> {
let path = req.get_path().expect("Failed to parse request path");
match path.as_str() {
"/logs" => serve_logs(bity_ic_canister_logger::export_logs()),
"/traces" => serve_logs(bity_ic_canister_logger::export_traces()),
"/metrics" => serve_metrics(),
_ => {
let asset_resp = serve_asset(&req);
trace(&format!("asset_resp: {:?}", asset_resp));
match asset_resp {
Some(response) => response,
None => {
if req.headers().to_vec().iter().any(|(k, v)| {
k == "referer"
&& v.contains(ic_cdk::api::canister_self().to_string().as_str())
}) {
return HttpResponse::builder()
Gwojda
February 11, 2026, 8:33am
6
Ok, i think i found the bug.
using xxx.icp0.io/xxx It’s working correctly. Using xxx.raw.icp0.io/xxx it’s not. The problem is here :
http-gateway/packages/ic-http-gateway/src/protocol/handler.rs at main · dfinity/http-gateway · GitHub
I guess we should do same as later in the code :
None => {
for HeaderField(name, value) in &agent_response.headers {
if !is_range_request
&& status_code == 206
&& (name.eq_ignore_ascii_case(http_header::CONTENT_RANGE.as_ref())
|| name.eq_ignore_ascii_case(http_header::CONTENT_LENGTH.as_ref()))
{
// skip copying
} else {
response_builder = response_builder.header(name.as_ref(), value.as_ref());
}
}
}
What do you think @rbirkner ?
I can open the pr if you want.
Edit : No certify assets streaming issue by Gwojda · Pull Request #61 · dfinity/http-gateway · GitHub
Hi @Gwojda
Sorry for the late reply! Thanks a lot for looking into it and coming up with a solution. At the moment, we just didn’t have the bandwidth to dig that deep.
We will review the PR and then make sure it gets deployed.