Skip to content

Commit 7b4287b

Browse files
committed
Merge branch 'main' of github.com:dfinity/response-verification into nathan/allow-additional-headers-for-redirects
2 parents 2f5aeff + b8aa830 commit 7b4287b

File tree

26 files changed

+1995
-866
lines changed

26 files changed

+1995
-866
lines changed

Cargo.lock

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

dfx.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"dfx": "0.23.0",
2+
"dfx": "0.24.3",
33
"output_env_file": ".env",
44
"version": 1,
55
"networks": {

examples/http-certification/assets/README.md

+15-10
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ fn post_upgrade() {
7676

7777
## Canister endpoints
7878

79-
There is only one canister endpoint in this example to serve assets, `http_request` query endpoint. The `serve_metrics` and `serve_asset` functions will be covered in a later section.
79+
There is only one canister endpoint in this example to serve assets, the `http_request` query endpoint. The `http_request` handler uses two auxiliary functions, `serve_metrics` and `serve_asset`, which are covered in a later section.
8080

8181
```rust
8282
#[query]
@@ -160,18 +160,17 @@ The `certify_all_assets` function performs the following steps:
160160
4. Certify the assets using the `certify_assets` function from the `ic-asset-certification` crate.
161161
5. Set the canister's certified data.
162162

163-
````rust
163+
```rust
164164
thread_local! {
165165
static HTTP_TREE: Rc<RefCell<HttpCertificationTree>> = Default::default();
166166

167+
static ASSET_ROUTER: RefCell<AssetRouter<'static>> = RefCell::new(AssetRouter::with_tree(HTTP_TREE.with(|tree| tree.clone())));
168+
167169
// initializing the asset router with an HTTP certification tree is optional.
168170
// if direct access to the HTTP certification tree is not needed for certifying
169171
// requests and responses outside of the asset router, then this step can be skipped
170172
// and the asset router can be initialized like so:
171-
// ```
172-
// static ASSET_ROUTER: RefCell<AssetRouter<'static>> = Default::default();
173-
// ```
174-
static ASSET_ROUTER: RefCell<AssetRouter<'static>> = RefCell::new(AssetRouter::with_tree(HTTP_TREE.with(|tree| tree.clone())));
173+
static ASSET_ROUTER: RefCell<AssetRouter<'static>> = Default::default();
175174
}
176175

177176
const IMMUTABLE_ASSET_CACHE_CONTROL: &str = "public, max-age=31536000, immutable";
@@ -230,7 +229,13 @@ fn certify_all_assets() {
230229
from: "/old-url".to_string(),
231230
to: "/".to_string(),
232231
kind: AssetRedirectKind::Permanent,
233-
headers: get_asset_headers(vec![]),
232+
headers: get_asset_headers(vec![
233+
("content-type".to_string(), "text/plain".to_string()),
234+
(
235+
"cache-control".to_string(),
236+
NO_CACHE_ASSET_CACHE_CONTROL.to_string(),
237+
),
238+
]),
234239
},
235240
];
236241

@@ -260,7 +265,7 @@ fn certify_all_assets() {
260265
set_certified_data(&asset_router.root_hash());
261266
});
262267
}
263-
````
268+
```
264269

265270
## Serving assets
266271

@@ -349,13 +354,13 @@ Then, deploy the canister:
349354
dfx deploy http_certification_assets_backend
350355
```
351356

352-
You can now access the canister's assets by navigating to the canister's URL in a web browser. The URL can also be found using the following command, making sure to replace `backend` with the name of the canister:
357+
You can now access the canister's assets by navigating to the canister's URL in a web browser. The URL can also be found using the following command:
353358

354359
```shell
355360
echo "http://$(dfx canister id http_certification_assets_backend).localhost:$(dfx info webserver-port)"
356361
```
357362

358-
Alternatively, to make a request with cURL, again making sure to replace `backend` with the name of the canister:
363+
Alternatively, to make a request with `curl`:
359364

360365
```shell
361366
curl "http://$(dfx canister id http_certification_assets_backend).localhost:$(dfx info webserver-port)" --resolve "$(dfx canister id http_certification_assets_backend).localhost:$(dfx info webserver-port):127.0.0.1"

examples/http-certification/custom-assets/README.md

+56-88
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ The lifecycle hooks are set up similarly to the JSON API.
6767
```rust
6868
#[init]
6969
fn init() {
70-
prepare_cel_exprs();
7170
certify_all_assets();
7271
}
7372

@@ -79,30 +78,17 @@ fn post_upgrade() {
7978

8079
## CEL Expressions
8180

82-
CEL expressions are also stored similarly to the [JSON API example](https://internetcomputer.org/docs/current/developer-docs/http-compatible-canisters/serving-json-over-http).
81+
The CEL expression definition is simpler in the case of assets compared to the [JSON API example](https://internetcomputer.org/docs/current/developer-docs/http-compatible-canisters/serving-json-over-http) as the same CEL expression is used for every asset, including the fallback response.
8382

8483
```rust
85-
thread_local! {
86-
static CEL_EXPRS: RefCell<HashMap<String, (DefaultResponseOnlyCelExpression<'static>, String)>> = RefCell::new(HashMap::new());
87-
}
88-
```
89-
90-
The CEL expression definition is simpler in the case of assets as the same CEL expression is used for every asset, including the fallback response.
91-
92-
```rust
93-
fn prepare_cel_exprs() {
94-
let asset_cel_expr_def = DefaultCelBuilder::response_only_certification()
95-
.with_response_certification(DefaultResponseCertification::response_header_exclusions(vec![]))
96-
.build();
97-
98-
let asset_cel_expr = asset_cel_expr_def.to_string();
99-
100-
CEL_EXPRS.with_borrow_mut(|exprs| {
101-
exprs.insert(
102-
ASSET_CEL_EXPR_PATH.to_string(),
103-
(asset_cel_expr_def, asset_cel_expr),
104-
);
105-
});
84+
lazy_static! {
85+
static ref ASSET_CEL_EXPR_DEF: DefaultResponseOnlyCelExpression<'static> =
86+
DefaultCelBuilder::response_only_certification()
87+
.with_response_certification(DefaultResponseCertification::response_header_exclusions(
88+
vec![],
89+
))
90+
.build();
91+
static ref ASSET_CEL_EXPR: String = ASSET_CEL_EXPR_DEF.to_string();
10692
}
10793
```
10894

@@ -172,11 +158,7 @@ fn create_asset_response(
172158
) -> HttpResponse {
173159
let headers = get_asset_headers(additional_headers, body.len(), cel_expr);
174160

175-
HttpResponse::builder()
176-
.with_status_code(200)
177-
.with_headers(headers)
178-
.with_body(body)
179-
.build()
161+
HttpResponse::ok(body, headers).build()
180162
}
181163
```
182164

@@ -189,35 +171,30 @@ fn certify_asset_response(
189171
asset_tree_path: &HttpCertificationPath,
190172
asset_req_path: String,
191173
) {
192-
CEL_EXPRS.with_borrow(|cel_exprs| {
193-
// get the relevant CEL expression
194-
let (cel_expr_def, cel_expr_str) = cel_exprs.get(*ASSET_CEL_EXPR_PATH).unwrap();
174+
// create the response
175+
let response = create_asset_response(additional_headers, body, ASSET_CEL_EXPR.clone());
195176

196-
// create the response
197-
let response = create_asset_response(additional_headers, body, cel_expr_str.to_string());
198-
199-
// certify the response
200-
let certification =
201-
HttpCertification::response_only(cel_expr_def, &response, None).unwrap();
177+
// certify the response
178+
let certification =
179+
HttpCertification::response_only(&ASSET_CEL_EXPR_DEF, &response, None).unwrap();
202180

203-
HTTP_TREE.with_borrow_mut(|http_tree| {
204-
// add the certification to the certification tree
205-
http_tree.insert(&HttpCertificationTreeEntry::new(
206-
asset_tree_path,
207-
&certification,
208-
));
209-
});
181+
HTTP_TREE.with_borrow_mut(|http_tree| {
182+
// add the certification to the certification tree
183+
http_tree.insert(&HttpCertificationTreeEntry::new(
184+
asset_tree_path,
185+
&certification,
186+
));
187+
});
210188

211-
RESPONSES.with_borrow_mut(|responses| {
212-
// store the response for later retrieval
213-
responses.insert(
214-
asset_req_path,
215-
CertifiedHttpResponse {
216-
response,
217-
certification,
218-
},
219-
);
220-
});
189+
RESPONSES.with_borrow_mut(|responses| {
190+
// store the response for later retrieval
191+
responses.insert(
192+
asset_req_path,
193+
CertifiedHttpResponse {
194+
response,
195+
certification,
196+
},
197+
);
221198
});
222199
}
223200
```
@@ -244,35 +221,30 @@ fn certify_asset_with_encoding(
244221
let mut headers = vec![("content-encoding".to_string(), encoding.to_string())];
245222
headers.extend(additional_headers);
246223

247-
CEL_EXPRS.with_borrow(|cel_exprs| {
248-
// get the relevant CEL expression
249-
let (cel_expr_def, cel_expr_str) = cel_exprs.get(*ASSET_CEL_EXPR_PATH).unwrap();
250-
251-
// create the response
252-
let response = create_asset_response(headers, body, cel_expr_str.to_string());
224+
// create the response
225+
let response = create_asset_response(headers, body, ASSET_CEL_EXPR.clone());
253226

254-
// certify the response
255-
let certification =
256-
HttpCertification::response_only(cel_expr_def, &response, None).unwrap();
227+
// certify the response
228+
let certification =
229+
HttpCertification::response_only(&ASSET_CEL_EXPR_DEF, &response, None).unwrap();
257230

258-
HTTP_TREE.with_borrow_mut(|http_tree| {
259-
// add the certification to the certification tree
260-
http_tree.insert(&HttpCertificationTreeEntry::new(
261-
asset_tree_path,
262-
&certification,
263-
));
264-
});
231+
HTTP_TREE.with_borrow_mut(|http_tree| {
232+
// add the certification to the certification tree
233+
http_tree.insert(&HttpCertificationTreeEntry::new(
234+
asset_tree_path,
235+
&certification,
236+
));
237+
});
265238

266-
ENCODED_RESPONSES.with_borrow_mut(|responses| {
267-
// store the response for later retrieval
268-
responses.insert(
269-
(asset_req_path, encoding.to_string()),
270-
CertifiedHttpResponse {
271-
response,
272-
certification,
273-
},
274-
);
275-
});
239+
ENCODED_RESPONSES.with_borrow_mut(|responses| {
240+
// store the response for later retrieval
241+
responses.insert(
242+
(asset_req_path, encoding.to_string()),
243+
CertifiedHttpResponse {
244+
response,
245+
certification,
246+
},
247+
);
276248
});
277249
};
278250
}
@@ -388,7 +360,7 @@ fn certify_index_asset() {
388360
}
389361
```
390362

391-
It's also possible to skip certification for certain routes. This can be useful for scenarios where it's difficult to predict what the response will look like for a certain route and the content is not very security sensitive. This can be done as follows:
363+
It's also possible to skip certification for certain routes. This can be useful for scenarios where it's difficult to predict what the response will look like for a certain route and the content is not very security sensitive. This can be done for example with metrics served on the `/metrics` route as follows:
392364

393365
```rust
394366
const METRICS_REQ_PATH: &str = "/metrics";
@@ -561,11 +533,7 @@ fn create_metrics_response() -> HttpResponse<'static> {
561533
DefaultCelBuilder::skip_certification().to_string(),
562534
);
563535

564-
HttpResponse::builder()
565-
.with_status_code(200)
566-
.with_headers(headers)
567-
.with_body(body)
568-
.build()
536+
HttpResponse::ok(body, headers).build()
569537
}
570538
```
571539

@@ -594,13 +562,13 @@ Then, deploy the canister:
594562
dfx deploy http_certification_custom_assets_backend
595563
```
596564

597-
You can now access the canister's assets by navigating to the canister's URL in a web browser. The URL can also be found using the following command, making sure to replace `backend` with the name of the canister:
565+
You can now access the canister's assets by navigating to the canister's URL in a web browser. The URL can also be found using the following command:
598566

599567
```shell
600568
echo "http://$(dfx canister id http_certification_custom_assets_backend).localhost:$(dfx info webserver-port)"
601569
```
602570

603-
Alternatively, to make a request with cURL, again making sure to replace `backend` with the name of the canister:
571+
Alternatively, to make a request with `curl`:
604572

605573
```shell
606574
curl "http://$(dfx canister id http_certification_custom_assets_backend).localhost:$(dfx info webserver-port)" --resolve "$(dfx canister id http_certification_custom_assets_backend).localhost:$(dfx info webserver-port):127.0.0.1"

0 commit comments

Comments
 (0)