Asset canister: HTTP headers Cache-Control and Access-Control-Allow-Origin

Is there a way to defined HTTP headers with the asset canister? Is it maybe possible to configure this dfx.json?


For performance reason, I have to define the Cache-Control headers of the icons, images, fonts and other JS assets of my web app.

These are also displayed by Lighthouse as errors, therefore, can also have an impact on the SEO ranking in addition.

If possible, it would be also nice if other headers such as Access-Control-Allow-Origin, which I use to make some icons available cross-domains, would be available.

With Firebase I currently set such headers as following in the local firebase.json configuration file:

{
  "hosting": {
    "public": "www",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    "headers": [
      {
        "source": "assets/icons/**/*",
        "headers": [
          {
            "key": "Access-Control-Allow-Origin",
            "value": "*"
          },
          {
            "key": "Cache-Control",
            "value": "max-age=31536000"
          }
        ]
      },
     {
        "source": "**/*.@(js|css)",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "max-age=31536000"
          }
        ]
      }
]
  }
}
5 Likes

I opened a feature request in the SDK

2 Likes

I did not tried it myself but dfx v0.11.0 supports configuring assets in assets canister - i.e. configuring http headers. Therefore I think this is solved :partying_face:.

Dfx release notes: sdk/CHANGELOG.adoc at master · dfinity/sdk · GitHub

Hi,

I’m trying to get the cache to work for static resources. But without success

I relied on the doc. New feature: support for configuring assets in assets canister

I created the .ic-assets.json file into the xx_frontend/assets directory

with the content:

[
  {
    "match": "**/*",
    "cache": {
      "max_age": 604800
    },
    "ignore": false
  }
]

I deleted the ./dist directory and deployed

Static resources aren’t cached.

I am using dfx 0.12.0-beta.3

I also tried:

[
  {
    "match": "**/*",
    "cache": {
      "max_age": 604800
    },
    "headers": {
      "Cache-control": "private, max-age=604800"
    },
    "ignore": false
  }
]

rename file .ic-assets.json into ic-assets.json

change “match”: “**/*”, to “match”: “*”,

use url xx.raw.ic0.app

Nothing is working for me !

Where I am wrong ?

As a part of my site is static it would be great to improve the response time.

Thanks for advices.

Hello @rbolog, we had to temporarily retract support for caching in dfx 0.11.2 – perhaps we haven’t described it well enough in our changelog, we’re sorry if this caused confusion.

Your first-described attempt will work once the feature will be enabled again:

I created the .ic-assets.json file into the xx_frontend/assets directory
with the content:

[
 {
   "match": "**/*",
   "cache": {
     "max_age": 604800
   },
  "ignore": false
 }
]

One more related FYIs: with dfx 0.12.0-beta.3, if you tried doing:

[
  {
    "match": "**/*",
    "cache": {
      "max_age": 604800
    },
    "headers": {
      "Cache-control": "private, max-age=604800"
    }
  }
]

it would cause a duplication of cache-control HTTP header, i.e. if you’d tried:

curl -vv https://canister-id.ic0.app/resource.html

you’d get back

< HTTP/1.1 200
< location: ...
< content-length: ...
< date: ...
< cache-control: max-age=604800
< cache-control: private, max-age=604800

This has recently been fixed, and will be part of next dfx release, you can find more details here: https://github.com/dfinity/sdk/pull/2689.

Asset canister currently undergoes a lot of changes, our hope is to make it rock solid before the end of this quarter, we’re kindly asking for your patience :slight_smile:

3 Likes

Many thanks for the cristal clear answers

1 Like

What takes precedence if using a custom asset canister and setting headers manually, the .ic-assets.json or the headers from the canister itself?

what do you mean by “custom asset canister”?

not the standard asset canister provided by dfinity, but a canister that implements the http_request method. the HttpResponse type has a headers field, are those overwritten when using the .ic-asset.json file?

Hard to tell without looking at the code, but in general one would need to explicitly add support for custom http headers. This would need to happen in the canister code (see how its implemented in frontend canister: sdk/state_machine.rs at master · dfinity/sdk · GitHub) and optionally client side – see how we’ve implemented it in dfx tooling:

ah ok, the .ic-asses.json is used by the asset canister itself! i thought this file is somehow used to configure the boundary nodes, but thinking about it that doesn’t make any sense.

so when i use a old Wasm of the asset canister (pre support for .ic-assets.json) having those headers set in the .ic-asset.json won’t do nothing as there’s no support for setting headers when uploading files to the asset canister. is that correct?

1 Like

correct, but you probably have to use something that uses the old ic-asset library as otherwise it’ll try to set the headers, which will get rejected because the interface does not allow headers to be set

1 Like

will this fail even if no .ic-assets.json file is present in a project?

Maybe… I think it’s easiest if you just try it out

I would like to customize Cache-Control headers, is there a reason why this is not supported?

You can since dfx 0.12.0. See the changelog entry here.

If you use the latest dfx 0.14.0 or higher the updated headers will automatically be updated. Before that you have to reinstall the canister for your new settings to apply

1 Like

As I understand it, the Cache-Control header only takes effect if I access the file via .raw.icp0.io

image

1.7s .icp0.io
4.2ms .raw.icp0.io

For now yes only raw.

However, if I understood correctly, with the new certified headers feature, it will be possible also on non raw domain to specify such hearders. It was plan to roll out this in dfx v0.14.0 but there was an issue. Don’t know the currenty status. @Severin and @NathanosDev know best.

1 Like

It should be working with dfx 0.14.1 over non-raw as well. If not that would be a bug

This is intentionally not working right now, the necessary changes will be deployed today.
For more context see this post: Important update for DFX v0.14.0 users