Skip to main content

AssetConfig

Enum AssetConfig 

Source
pub enum AssetConfig {
    File {
        path: String,
        content_type: Option<String>,
        headers: Vec<(String, String)>,
        fallback_for: Vec<AssetFallbackConfig>,
        aliased_by: Vec<String>,
        encodings: Vec<(AssetEncoding, String)>,
    },
    Pattern {
        pattern: String,
        content_type: Option<String>,
        headers: Vec<(String, String)>,
        encodings: Vec<(AssetEncoding, String)>,
    },
    Redirect {
        from: String,
        to: String,
        kind: AssetRedirectKind,
        headers: Vec<(String, String)>,
    },
}
Expand description

Certification configuration for assets. This configuration is passed alongside the assets to the AssetRouter.

The configuration can target a specific File or an array of files using a Pattern.

Configuration can specify the content type and headers to include for certification and to be served by the AssetRouter for each asset matching the configuration.

§Examples

§JavaScript file

This example configures an individual JavaScript file to be served by the AssetRouter on the /app.js path. The content type is set to text/javascript and a cache-control header is added.

use ic_http_certification::StatusCode;
use ic_asset_certification::{AssetConfig, AssetEncoding};

let config = AssetConfig::File {
    path: "app.js".to_string(),
    content_type: Some("text/javascript".to_string()),
    headers: vec![
        ("Cache-Control".to_string(), "public, max-age=31536000, immutable".to_string()),
    ],
    fallback_for: vec![],
    aliased_by: vec![],
    encodings: vec![
        AssetEncoding::Brotli.default_config(),
        AssetEncoding::Gzip.default_config(),
    ],
};

§Index HTML file with fallback

This example configures an individual HTML file to be served by the AssetRouter on the /index.html path. In addition, it is configured as the fallback for the / scope. This means that any request that does not exactly match an asset, will be given this response. The content type is set to text/html and a cache-control header is added.

use ic_http_certification::StatusCode;
use ic_asset_certification::{AssetConfig, AssetFallbackConfig, AssetEncoding};

let config = AssetConfig::File {
    path: "index.html".to_string(),
    content_type: Some("text/html".to_string()),
    headers: vec![
        ("Cache-Control".to_string(), "public, no-cache, no-store".to_string()),
    ],
    fallback_for: vec![AssetFallbackConfig {
        scope: "/".to_string(),
        status_code: Some(StatusCode::OK),
    }],
    aliased_by: vec!["/".to_string()],
    encodings: vec![
        AssetEncoding::Brotli.default_config(),
        AssetEncoding::Gzip.default_config(),
    ],
};

§404 HTML file with multiple fallbacks and aliases

This example configures an individual HTML file to be served by the AssetRouter on the /404.html path.

In addition, it is configured as the fallback for the /js, and /css scopes. This means that any request that does not exactly match an asset in the /js or /css directories, will be given this response. The content type is set to text/html and a cache-control header is added.

The asset is also aliased by multiple paths. This means that any request made to one of these aliases will be served the asset at /404.html. The asset is aliased by the following paths: - /404 - /404/ - /404.html - /not-found - /not-found/ - /not-found/index.html

use ic_http_certification::StatusCode;
use ic_asset_certification::{AssetConfig, AssetFallbackConfig, AssetEncoding};

let config = AssetConfig::File {
    path: "404.html".to_string(),
    content_type: Some("text/html".to_string()),
    headers: vec![
        ("Cache-Control".to_string(), "public, no-cache, no-store".to_string()),
    ],
    fallback_for: vec![
        AssetFallbackConfig {
            scope: "/css".to_string(),
            status_code: Some(StatusCode::NOT_FOUND),
        },
        AssetFallbackConfig {
            scope: "/js".to_string(),
            status_code: Some(StatusCode::NOT_FOUND),
        },
    ],
    aliased_by: vec![
        "/404".to_string(),
        "/404/".to_string(),
        "/404.html".to_string(),
        "/not-found".to_string(),
        "/not-found/".to_string(),
        "/not-found/index.html".to_string(),
   ],
    encodings: vec![
        AssetEncoding::Brotli.default_config(),
        AssetEncoding::Gzip.default_config(),
    ],
};

§CSS files using a glob pattern

This example configures all CSS files to be served by the AssetRouter using a glob pattern. The content type is set to text/css and a cache-control header is added.

use ic_http_certification::StatusCode;
use ic_asset_certification::{AssetConfig, AssetEncoding};

let config = AssetConfig::Pattern {
    pattern: "**/*.css".to_string(),
    content_type: Some("text/css".to_string()),
    headers: vec![
        ("Cache-Control".to_string(), "public, max-age=31536000, immutable".to_string()),
    ],
    encodings: vec![
        AssetEncoding::Brotli.default_config(),
        AssetEncoding::Gzip.default_config(),
    ],
};

§Temporary redirect

This example configures a redirect from /old to /new. The redirect is configured as a temporary redirect (307).

use ic_asset_certification::{AssetConfig, AssetRedirectKind};

let config = AssetConfig::Redirect {
    from: "/old".to_string(),
    to: "/new".to_string(),
    kind: AssetRedirectKind::Temporary,
    headers: vec![(
        "content-type".to_string(),
        "text/plain; charset=utf-8".to_string(),
    )],
};

§Permanent redirect

This example configures a redirect from /old to /new. The redirect is configured as a permanent redirect (301).

use ic_asset_certification::{AssetConfig, AssetRedirectKind};

let config = AssetConfig::Redirect {
    from: "/old".to_string(),
    to: "/new".to_string(),
    kind: AssetRedirectKind::Permanent,
    headers: vec![(
        "content-type".to_string(),
        "text/plain; charset=utf-8".to_string(),
    )],
};

Variants§

§

File

Matches a specific file.

Fields

§path: String

The path to the file. This path must exactly match the path of an Asset provided to the AssetRouter with this config.

§content_type: Option<String>

The content type of the file (e.g. “text/javascript”).

Providing this option will auto-insert a Content-Type header with the provided value. If this value is not provided, the Content-Type header will not be inserted.

If the Content-Type header is not sent to the browser, the browser will try to guess the content type based on the file extension, unless a X-Content-Type-Options: nosniff header is sent.

Not certifying the Content-Type header will also allow a malicious replica to insert its own Content-Type header, which could lead to a security vulnerability.

§headers: Vec<(String, String)>

Additional headers to be inserted into the response. Each additional header added will be included in certification and served by the AssetRouter for matching Assets.

§fallback_for: Vec<AssetFallbackConfig>

Configure this asset as a fallback for a set of scopes.

When serving assets, if a requested path does not exactly match any assets then the AssetRouter will search for an asset configured with a fallback scope that most closely matches the requested asset’s path.

For example, if a request is made for /app.js and no asset with that exact path is found, the router will attempt to serve an asset configured with a fallback scope of /.

This will be done recursively until no more fallback scopes are possible to find. For example, if a request is made for /assets/js/app/core/index.js and no asset with that exact path is found, the AssetRouter will search for assets configured with the following fallback scopes, in order:

  • /assets/js/app/core
  • /assets/js/app
  • /assets/js
  • /assets
  • /

If multiple fallback assets are configured, the first one found will be used. If no asset is found with any of these fallback scopes, no response will be returned.

§aliased_by: Vec<String>

A list of aliases for this asset. If a request is made for one of these aliases, the asset will be served as if the request was made for the original path.

For example, if an asset is configured with the path index.html and the alias /, a request for / will be served the asset at index.html.

§encodings: Vec<(AssetEncoding, String)>

A list of encodings to serve the asset with. Each listing includes the encoding of an asset, and the file extension for the encoded asset. The router will search for an asset with the provided file extension and certify all matching encoded assets, if found.

A list of alternative encodings that can be used to serve the asset.

Each entry is a tuple of the encoding name and the file extension used in the file path. For example, to include Brotli and Gzip encodings: vec![AssetEncoding::Brotli.default_config(), AssetEncoding::Gzip.default_config()]

Each encoding referenced must be provided to the asset router as a separate file with the same filename as the original file, but with an additional file extension matching the configuration. For example, if the current matched file is named file.html, then the asset router will look for file.html.br and file.html.gz.

If the file is found, the asset will be certified and served with the provided encoding according to the Accept-Encoding. Encodings are prioritized in the following order: - Brotli - Zstd - Gzip - Deflate - Identity

The asset router will return the highest priority encoding that has been certified and is supported by the client.

§

Pattern

Matches files using a glob pattern.

Fields

§pattern: String

A glob pattern to match files against.

Standard Unix-style glob syntax is supported:

  • ? matches any single character.
  • * matches zero or more characters.
  • ** recursively matches directories but is only legal in three situations.
    • If the glob starts with **/, then it matches all directories. For example, **/foo matches foo and bar/foo but not foo/bar.
    • If the glob ends with /**, then it matches all sub-entries. For example, foo/** matches foo/a and foo/a/b, but not foo.
    • If the glob contains /**/ anywhere within the pattern, then it matches zero or more directories.
    • Using ** anywhere else is illegal.
    • The glob ** is allowed and means “match everything”.
  • {a,b} matches a or b where a and b are arbitrary glob patterns. (N.B. Nesting {…} is not currently allowed.)
  • [ab] matches a or b where a and b are characters.
  • [!ab] to match any character except for a and b.
  • Metacharacters such as * and ? can be escaped with character class notation. e.g., [*] matches *.
§content_type: Option<String>

The content type of the file (e.g. “text/javascript”).

Providing this option will auto-insert a Content-Type header with the provided value. If this value is not provided, the Content-Type header will not be inserted.

If the Content-Type header is not sent to the browser, the browser will try to guess the content type based on the file extension, unless a X-Content-Type-Options: nosniff header is sent.

Not certifying the Content-Type header will also allow a malicious replica to insert its own Content-Type header, which could lead to a security vulnerability.

§headers: Vec<(String, String)>

Additional headers to be inserted into the response. Each additional header added will be included in certification and served by the AssetRouter for matching Assets.

§encodings: Vec<(AssetEncoding, String)>

A list of encodings to serve the asset with. Each listing includes the encoding of an asset, and the file extension for the encoded asset. The router will search for an asset with the provided file extension and certify all matching encoded assets, if found.

A list of alternative encodings that can be used to serve the asset.

Each entry is a tuple of the encoding name and the file extension used in the file path. For example, to include Brotli and Gzip encodings: vec![AssetEncoding::Brotli.default_config(), AssetEncoding::Gzip.default_config()]

Each encoding referenced must be provided to the asset router as a separate file with the same filename as the original file, but with an additional file extension matching the configuration. For example, if the current matched file is named file.html, then the asset router will look for file.html.br and file.html.gz.

If the file is found, the asset will be certified and served with the provided encoding according to the Accept-Encoding. Encodings are prioritized in the following order: - Brotli - Zstd - Gzip - Deflate - Identity

The asset router will return the highest priority encoding that has been certified and is supported by the client.

§

Redirect

Redirects the request to another URL. This config type is not matched against any assets.

Fields

§from: String

The URL to redirect from.

§to: String

The URL to redirect to.

§kind: AssetRedirectKind

The kind redirect to configure.

§headers: Vec<(String, String)>

Additional headers to be inserted into the response. Each additional header added will be included in certification and served by the AssetRouter for matching Assets.

Note that the Location header will be automatically added to the response with the value of the to field.

Trait Implementations§

Source§

impl Clone for AssetConfig

Source§

fn clone(&self) -> AssetConfig

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for AssetConfig

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.