Skip to content

Commit fefe1dc

Browse files
authored
feat(ic-asset-certification): add ability to delete assets by path (#402)
1 parent dd7d8d6 commit fefe1dc

File tree

6 files changed

+921
-154
lines changed

6 files changed

+921
-154
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/ic-asset-certification/README.md

+184-7
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,15 @@ add_v2_certificate_header(
513513

514514
## Deleting assets
515515

516-
Deleting assets is similar to (certifying them)[#inserting-assets-into-the-asset-router].
516+
There are three ways to delete assets from the asset router:
517+
518+
1. [By configuration](#deleting-assets-by-configuration).
519+
1. [By path](#deleting-assets-by-path).
520+
1. [All at once](#deleting-all-assets).
521+
522+
### Deleting assets by configuration
523+
524+
Deleting assets by configuration is similar to (certifying them)[#inserting-assets-into-the-asset-router].
517525

518526
Depending on the configuration provided to the `certify_assets` function,
519527
multiple responses may be generated for the same asset. To ensure that all generated responses are deleted,
@@ -530,7 +538,7 @@ If the configuration excludes a file that was certified, it will not be deleted.
530538
provided to `certify_assets` includes the Brotli and Gzip encodings, but the configuration provided to `delete_assets`
531539
only includes Brotli, then the Gzip file will not be deleted.
532540

533-
Using the same base example used to demonstrate certifying assets:
541+
Assuming the same base example used above to demonstrate certifying assets:
534542

535543
```rust
536544
use ic_http_certification::StatusCode;
@@ -727,10 +735,6 @@ asset_router.delete_assets(
727735
And finally, to delete the `/old` redirect:
728736

729737
```rust
730-
# use ic_asset_certification::{Asset, AssetConfig, AssetFallbackConfig, AssetRouter, AssetRedirectKind, AssetEncoding};
731-
732-
# let mut asset_router = AssetRouter::default();
733-
734738
asset_router
735739
.delete_assets(
736740
vec![],
@@ -746,18 +750,191 @@ asset_router
746750
After deleting any assets, make sure to set the canister's
747751
certified data again:
748752

749-
```ignore
753+
```rust
754+
use ic_cdk::api::set_certified_data;
755+
756+
set_certified_data(&asset_router.root_hash());
757+
```
758+
759+
### Deleting assets by path
760+
761+
To delete assets by path, use the
762+
[delete_assets_by_path](AssetRouter::delete_assets_by_path) function.
763+
764+
Depending on the configuration provided to the [certify_assets](AssetRouter::certify_assets) function,
765+
multiple responses may be generated for the same asset. These assets may exist on different paths,
766+
for example if the `alias` configuration is used. If `alias` paths are not passed to this function,
767+
they will not be deleted.
768+
769+
If multiple encodings exist for a path, all encodings will be deleted.
770+
771+
Fallbacks are also not deleted, to delete them, use the
772+
[delete_fallback_assets_by_path](AssetRouter::delete_fallback_assets_by_path) function.
773+
774+
Assuming the same base example used above to demonstrate certifying assets:
775+
776+
```rust
777+
use ic_http_certification::StatusCode;
778+
use ic_asset_certification::{Asset, AssetConfig, AssetFallbackConfig, AssetRouter, AssetRedirectKind, AssetEncoding};
779+
780+
let mut asset_router = AssetRouter::default();
781+
782+
let assets = vec![
783+
Asset::new(
784+
"index.html",
785+
b"<html><body><h1>Hello World!</h1></body></html>".as_slice(),
786+
),
787+
Asset::new(
788+
"index.html.gz",
789+
&[0, 1, 2, 3, 4, 5]
790+
),
791+
Asset::new(
792+
"index.html.br",
793+
&[6, 7, 8, 9, 10, 11]
794+
),
795+
Asset::new(
796+
"app.js",
797+
b"console.log('Hello World!');".as_slice(),
798+
),
799+
Asset::new(
800+
"app.js.gz",
801+
&[12, 13, 14, 15, 16, 17],
802+
),
803+
Asset::new(
804+
"app.js.br",
805+
&[18, 19, 20, 21, 22, 23],
806+
),
807+
Asset::new(
808+
"css/app-ba74b708.css",
809+
b"html,body{min-height:100vh;}".as_slice(),
810+
),
811+
Asset::new(
812+
"css/app-ba74b708.css.gz",
813+
&[24, 25, 26, 27, 28, 29],
814+
),
815+
Asset::new(
816+
"css/app-ba74b708.css.br",
817+
&[30, 31, 32, 33, 34, 35],
818+
),
819+
];
820+
821+
let asset_configs = vec![
822+
AssetConfig::File {
823+
path: "index.html".to_string(),
824+
content_type: Some("text/html".to_string()),
825+
headers: vec![(
826+
"cache-control".to_string(),
827+
"public, no-cache, no-store".to_string(),
828+
)],
829+
fallback_for: vec![AssetFallbackConfig {
830+
scope: "/".to_string(),
831+
status_code: Some(StatusCode::OK),
832+
}],
833+
aliased_by: vec!["/".to_string()],
834+
encodings: vec![
835+
AssetEncoding::Brotli.default_config(),
836+
AssetEncoding::Gzip.default_config(),
837+
],
838+
},
839+
AssetConfig::Pattern {
840+
pattern: "**/*.js".to_string(),
841+
content_type: Some("text/javascript".to_string()),
842+
headers: vec![(
843+
"cache-control".to_string(),
844+
"public, max-age=31536000, immutable".to_string(),
845+
)],
846+
encodings: vec![
847+
AssetEncoding::Brotli.default_config(),
848+
AssetEncoding::Gzip.default_config(),
849+
],
850+
},
851+
AssetConfig::Pattern {
852+
pattern: "**/*.css".to_string(),
853+
content_type: Some("text/css".to_string()),
854+
headers: vec![(
855+
"cache-control".to_string(),
856+
"public, max-age=31536000, immutable".to_string(),
857+
)],
858+
encodings: vec![
859+
AssetEncoding::Brotli.default_config(),
860+
AssetEncoding::Gzip.default_config(),
861+
],
862+
},
863+
AssetConfig::Redirect {
864+
from: "/old".to_string(),
865+
to: "/new".to_string(),
866+
kind: AssetRedirectKind::Permanent,
867+
},
868+
];
869+
870+
asset_router.certify_assets(assets, asset_configs).unwrap();
871+
```
872+
873+
To delete the `index.html` asset, along with the fallback configuration for the `/` scope, the alias `/` and the alternative encodings:
874+
875+
```rust
876+
asset_router
877+
.delete_assets_by_path(
878+
vec![
879+
"/index.html", // deletes the index.html asset, along with all encodings
880+
"/" // deletes the `/` alias for index.html, along with all encodings
881+
],
882+
)
883+
.unwrap();
884+
885+
asset_router
886+
.delete_fallback_assets_by_path(
887+
vec![
888+
"/" // deletes the fallback configuration for the `/` scope, along with all encodings
889+
]
890+
)
891+
.unwrap();
892+
```
893+
894+
To delete the `app.js`asset, along with the alternative encodings:
895+
896+
```rust
897+
asset_router.delete_assets(vec!["/app.js"]).unwrap();
898+
```
899+
900+
To delete the `css/app-ba74b708.css` asset, along with the alternative encodings:
901+
902+
```rust
903+
asset_router.delete_assets(vec!["/css/app-ba74b708.css"]).unwrap();
904+
```
905+
906+
And finally, to delete the `/old` redirect:
907+
908+
```rust
909+
asset_router.delete_assets_by_path(vec!["/old"]).unwrap();
910+
```
911+
912+
After deleting any assets, make sure to set the canister's
913+
certified data again:
914+
915+
```rust
750916
use ic_cdk::api::set_certified_data;
751917

752918
set_certified_data(&asset_router.root_hash());
753919
```
754920

921+
### Deleting all assets
922+
755923
It's also possible to delete all assets and their certification in one go:
756924

757925
```rust
758926
asset_router.delete_all_assets();
759927
```
760928

929+
After deleting any assets, make sure to set the canister's
930+
certified data again:
931+
932+
```rust
933+
use ic_cdk::api::set_certified_data;
934+
935+
set_certified_data(&asset_router.root_hash());
936+
```
937+
761938
## Querying assets
762939

763940
The `AssetRouter` has two functions to retrieve an `AssetMap` containing assets.

0 commit comments

Comments
 (0)