Skip to content

Commit

Permalink
refactor: add default mapping for asset encodings
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanosdev committed Aug 13, 2024
1 parent 96094d1 commit 970995d
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 68 deletions.
17 changes: 16 additions & 1 deletion examples/http-certification/assets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default defineConfig({
viteCompressionPlugin({
algorithm: 'gzip',
// this extension will be referenced later in the canister code
ext: '.gzip',
ext: '.gz',
// ensure to not delete the original files
deleteOriginFile: false,
threshold: 0,
Expand Down Expand Up @@ -165,6 +165,11 @@ const IMMUTABLE_ASSET_CACHE_CONTROL: &str = "public, max-age=31536000, immutable

fn certify_all_assets() {
// 1. Define the asset certification configurations.
let encodings = vec![
AssetEncoding::Brotli.default(),
AssetEncoding::Gzip.default(),
];

let asset_configs = vec![
AssetConfig::File {
path: "index.html".to_string(),
Expand All @@ -177,6 +182,7 @@ fn certify_all_assets() {
scope: "/".to_string(),
}],
aliased_by: vec!["/".to_string()],
encodings: encodings.clone(),
},
AssetConfig::Pattern {
pattern: "**/*.js".to_string(),
Expand All @@ -185,6 +191,7 @@ fn certify_all_assets() {
"cache-control".to_string(),
IMMUTABLE_ASSET_CACHE_CONTROL.to_string(),
)]),
encodings: encodings.clone(),
},
AssetConfig::Pattern {
pattern: "**/*.css".to_string(),
Expand All @@ -193,6 +200,7 @@ fn certify_all_assets() {
"cache-control".to_string(),
IMMUTABLE_ASSET_CACHE_CONTROL.to_string(),
)]),
encodings,
},
AssetConfig::Pattern {
pattern: "**/*.ico".to_string(),
Expand All @@ -201,6 +209,7 @@ fn certify_all_assets() {
"cache-control".to_string(),
IMMUTABLE_ASSET_CACHE_CONTROL.to_string(),
)]),
encodings: vec![],
},
AssetConfig::Pattern {
pattern: "**/*.svg".to_string(),
Expand All @@ -209,6 +218,12 @@ fn certify_all_assets() {
"cache-control".to_string(),
IMMUTABLE_ASSET_CACHE_CONTROL.to_string(),
)]),
encodings: vec![],
},
AssetConfig::Redirect {
from: "/old-url".to_string(),
to: "/".to_string(),
kind: AssetRedirectKind::Permanent,
},
];

Expand Down
4 changes: 2 additions & 2 deletions examples/http-certification/assets/src/backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ fn collect_assets<'content, 'path>(
fn certify_all_assets() {
// 1. Define the asset certification configurations.
let encodings = vec![
(AssetEncoding::Brotli, "br".to_string()),
(AssetEncoding::Gzip, "gzip".to_string()),
AssetEncoding::Brotli.default(),
AssetEncoding::Gzip.default(),
];

let asset_configs = vec![
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default defineConfig({
viteCompressionPlugin({
algorithm: 'gzip',
// this extension will be referenced later in the canister code
ext: '.gzip',
ext: '.gz',
// ensure to not delete the original files
deleteOriginFile: false,
threshold: 0,
Expand Down
41 changes: 25 additions & 16 deletions packages/ic-asset-certification/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,18 @@ In both cases, the following options can be configured for each asset:
- `encodings`
- A list of alternative encodings that can be used to serve the asset.
- Each entry is a tuple of the [encoding name](AssetEncoding) and the file
extension used in the file path.
For example, to include Brotli and Gzip encodings:
`vec![(AssetEncoding::Brotli, "br".to_string()), AssetEncoding::Gzip, "gz".to_string())]`.
extension used in the file path, that can be conveniently created with
the `default` factory method. For example, to include Brotli and Gzip encodings:
`vec![AssetEncoding::Brotli.default(), AssetEncoding::Gzip.default()]`.
- The default file extensions for each encoding are:
- Brotli: `br`
- Gzip: `gz`
- Deflate: `zz`
- Zstd: `zst`
- Alternatively, a custom file extension can be provided for each encoding
by using the `custom` factory method. For example, to include a custom
file extension for Brotli and Gzip encodings:
`vec![AssetEncoding::Brotli.custom("brotli"), AssetEncoding::Gzip.custom("gzip")]`.
- 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
Expand Down Expand Up @@ -169,8 +178,8 @@ let config = AssetConfig::File {
}],
aliased_by: vec!["/".to_string()],
encodings: vec![
(AssetEncoding::Brotli, "br".to_string()),
(AssetEncoding::Gzip, "gz".to_string()),
AssetEncoding::Brotli.default(),
AssetEncoding::Gzip.default()
],
};
```
Expand Down Expand Up @@ -220,8 +229,8 @@ let config = AssetConfig::File {
"/not-found/index.html".to_string(),
],
encodings: vec![
(AssetEncoding::Brotli, "br".to_string()),
(AssetEncoding::Gzip, "gz".to_string()),
AssetEncoding::Brotli.default(),
AssetEncoding::Gzip.default(),
],
};
```
Expand Down Expand Up @@ -267,8 +276,8 @@ let config = AssetConfig::Pattern {
("Cache-Control".to_string(), "public, max-age=31536000, immutable".to_string()),
],
encodings: vec![
(AssetEncoding::Brotli, "br".to_string()),
(AssetEncoding::Gzip, "gz".to_string()),
AssetEncoding::Brotli.default(),
AssetEncoding::Gzip.default(),
],
};
```
Expand Down Expand Up @@ -317,7 +326,7 @@ let config = AssetConfig::Redirect {
The `AssetRouter` is responsible for certifying responses and routing requests to
the appropriate response.

Assets can be inserted in bulk using the `certify_assets` method:
Assets can be inserted using the `certify_assets` method:

```rust
use ic_asset_certification::{Asset, AssetConfig, AssetFallbackConfig, AssetRouter, AssetRedirectKind};
Expand Down Expand Up @@ -376,8 +385,8 @@ let asset_configs = vec![
}],
aliased_by: vec!["/".to_string()],
encodings: vec![
(AssetEncoding::Brotli, "br".to_string()),
(AssetEncoding::Gzip, "gz".to_string()),
AssetEncoding::Brotli.default(),
AssetEncoding::Gzip.default(),
],
},
AssetConfig::Pattern {
Expand All @@ -388,8 +397,8 @@ let asset_configs = vec![
"public, max-age=31536000, immutable".to_string(),
)],
encodings: vec![
(AssetEncoding::Brotli, "br".to_string()),
(AssetEncoding::Gzip, "gz".to_string()),
AssetEncoding::Brotli.default(),
AssetEncoding::Gzip.default(),
],
},
AssetConfig::Pattern {
Expand All @@ -400,8 +409,8 @@ let asset_configs = vec![
"public, max-age=31536000, immutable".to_string(),
)],
encodings: vec![
(AssetEncoding::Brotli, "br".to_string()),
(AssetEncoding::Gzip, "gz".to_string()),
AssetEncoding::Brotli.default(),
AssetEncoding::Gzip.default(),
],
},
AssetConfig::Redirect {
Expand Down
85 changes: 71 additions & 14 deletions packages/ic-asset-certification/src/asset_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ use std::fmt::{Display, Formatter};
/// fallback_for: vec![],
/// aliased_by: vec![],
/// encodings: vec![
/// (AssetEncoding::Brotli, "br".to_string()),
/// (AssetEncoding::Gzip, "gz".to_string()),
/// AssetEncoding::Brotli.default(),
/// AssetEncoding::Gzip.default(),
/// ],
/// };
/// ```
Expand All @@ -61,8 +61,8 @@ use std::fmt::{Display, Formatter};
/// }],
/// aliased_by: vec!["/".to_string()],
/// encodings: vec![
/// (AssetEncoding::Brotli, "br".to_string()),
/// (AssetEncoding::Gzip, "gz".to_string()),
/// AssetEncoding::Brotli.default(),
/// AssetEncoding::Gzip.default(),
/// ],
/// };
/// ```
Expand Down Expand Up @@ -113,8 +113,8 @@ use std::fmt::{Display, Formatter};
/// "/not-found/index.html".to_string(),
/// ],
/// encodings: vec![
/// (AssetEncoding::Brotli, "br".to_string()),
/// (AssetEncoding::Gzip, "gz".to_string()),
/// AssetEncoding::Brotli.default(),
/// AssetEncoding::Gzip.default(),
/// ],
/// };
/// ```
Expand All @@ -135,8 +135,8 @@ use std::fmt::{Display, Formatter};
/// ("Cache-Control".to_string(), "public, max-age=31536000, immutable".to_string()),
/// ],
/// encodings: vec![
/// (AssetEncoding::Brotli, "br".to_string()),
/// (AssetEncoding::Gzip, "gz".to_string()),
/// AssetEncoding::Brotli.default(),
/// AssetEncoding::Gzip.default(),
/// ],
/// };
/// ```
Expand Down Expand Up @@ -245,7 +245,7 @@ pub enum AssetConfig {
/// Each entry is a tuple of the [encoding name](AssetEncoding) and the
/// file extension used in the file path. For example, to include Brotli
/// and Gzip encodings:
/// `vec![(AssetEncoding::Brotli, "br".to_string()), (AssetEncoding::Gzip, "gz".to_string())]`
/// `vec![AssetEncoding::Brotli.default(), AssetEncoding::Gzip.default()]`
///
/// Each encoding referenced must be provided to the asset router as a
/// separate file with the same filename as the original file, but with
Expand Down Expand Up @@ -324,7 +324,7 @@ pub enum AssetConfig {
/// Each entry is a tuple of the [encoding name](AssetEncoding) and the
/// file extension used in the file path. For example, to include Brotli
/// and Gzip encodings:
/// `vec![(AssetEncoding::Brotli, "br".to_string()), (AssetEncoding::Gzip, "gz".to_string())]`
/// `vec![AssetEncoding::Brotli.default(), AssetEncoding::Gzip.default()]`
///
/// Each encoding referenced must be provided to the asset router as a
/// separate file with the same filename as the original file, but with
Expand Down Expand Up @@ -417,9 +417,68 @@ pub enum AssetEncoding {

/// The asset is encoded with the Deflate algorithm.
Deflate,
}

impl AssetEncoding {
/// Returns the default encoding and file extension for the encoding.
/// The default encoding is the encoding that is used when the client
/// does not specify an encoding in the `Accept-Encoding` header.
///
/// The default encoding and file extension are:
/// - [Brotli](AssetEncoding::Brotli): `br`
/// - [Zstd](AssetEncoding::Zstd): `zst`
/// - [Gzip](AssetEncoding::Gzip): `gz`
/// - [Deflate](AssetEncoding::Deflate): `zz`
///
/// # Examples
///
/// ```
/// use ic_asset_certification::AssetEncoding;
///
/// let (encoding, extension) = AssetEncoding::Brotli.default();
/// assert_eq!(encoding, AssetEncoding::Brotli);
/// assert_eq!(extension, "br");
///
/// let (encoding, extension) = AssetEncoding::Zstd.default();
/// assert_eq!(encoding, AssetEncoding::Zstd);
/// assert_eq!(extension, "zst");
///
/// let (encoding, extension) = AssetEncoding::Gzip.default();
/// assert_eq!(encoding, AssetEncoding::Gzip);
/// assert_eq!(extension, "gz");
///
/// let (encoding, extension) = AssetEncoding::Deflate.default();
/// assert_eq!(encoding, AssetEncoding::Deflate);
/// assert_eq!(extension, "zz");
/// ```
pub fn default(self) -> (AssetEncoding, String) {
let file_extension = match self {
AssetEncoding::Brotli => "br".to_string(),
AssetEncoding::Zstd => "zst".to_string(),
AssetEncoding::Gzip => "gz".to_string(),
AssetEncoding::Deflate => "zz".to_string(),
};

/// The asset is not encoded.
Identity,
(self, file_extension)
}

/// Returns an encoding with a custom file extension. This is useful
/// when the default file extension assigned by [default](AssetEncoding::default)
/// is not desired.
///
/// # Examples
///
/// ```
/// use ic_asset_certification::AssetEncoding;
///
/// let (encoding, extension) = AssetEncoding::Brotli.custom("brotli".to_string());
///
/// assert_eq!(encoding, AssetEncoding::Brotli);
/// assert_eq!(extension, "brotli");
/// ```
pub fn custom(self, extension: String) -> (AssetEncoding, String) {
(self, extension)
}
}

impl Display for AssetEncoding {
Expand All @@ -429,7 +488,6 @@ impl Display for AssetEncoding {
AssetEncoding::Zstd => "zstd".to_string(),
AssetEncoding::Gzip => "gzip".to_string(),
AssetEncoding::Deflate => "deflate".to_string(),
AssetEncoding::Identity => "identity".to_string(),
};

write!(f, "{}", str)
Expand Down Expand Up @@ -660,6 +718,5 @@ mod tests {
assert_eq!(AssetEncoding::Zstd.to_string(), "zstd");
assert_eq!(AssetEncoding::Gzip.to_string(), "gzip");
assert_eq!(AssetEncoding::Deflate.to_string(), "deflate");
assert_eq!(AssetEncoding::Identity.to_string(), "identity");
}
}
Loading

0 comments on commit 970995d

Please sign in to comment.