From 123133ca50a844ef7a881754ed6b15da13202df0 Mon Sep 17 00:00:00 2001 From: NathanosDev Date: Thu, 30 Nov 2023 13:23:04 +0100 Subject: [PATCH] feat: add copy on write support to CEL definition types --- packages/ic-http-certification/README.md | 54 ++++++----- .../src/cel/cel_builder.rs | 95 ++++++++++--------- .../src/cel/cel_types.rs | 29 +++++- .../src/cel/create_cel_expr.rs | 45 ++++----- packages/ic-http-certification/src/lib.rs | 50 +++++----- 5 files changed, 151 insertions(+), 122 deletions(-) diff --git a/packages/ic-http-certification/README.md b/packages/ic-http-certification/README.md index bf55444f..e5d7bfa5 100644 --- a/packages/ic-http-certification/README.md +++ b/packages/ic-http-certification/README.md @@ -29,11 +29,11 @@ let cel_expr = create_cel_expr(&certification); ### Using the CEL builder -The CEL builder interface is provided to ease the creation of CEL expressions through an ergonmic interface. If this interface does not meet your needs, you can also [create CEL expressions directly](#directly-creating-a-cel-expression). To define a CEL expression, start with [DefaultCelBuilder]. This struct provides a set of methods that can be used to define how your request and response pair should be certified. +The CEL builder interface is provided to ease the creation of CEL expressions through an ergonmic interface. If this interface does not meet your needs, you can also [create CEL expressions directly](#directly-creating-a-cel-expression). To define a CEL expression, start with `DefaultCelBuilder`. This struct provides a set of methods that can be used to define how your request and response pair should be certified. -When certifying requests, the request body and method are always certified. To additionally certify request headers and query parameters, use `with_request_headers` and `with_request_query_parameters` respectively. Both methods take a [str] slice as an argument. +When certifying requests, the request body and method are always certified. To additionally certify request headers and query parameters, use `with_request_headers` and `with_request_query_parameters` respectively. Both methods take a `str` slice as an argument. -When certifying a response, the response body and status code are always certified. To additionally certify response headers, use `with_response_certification`. This method takes the `DefaultResponseCertification` enum as an argument. To specify header inclusions, use the `CertifiedResponseHeaders` variant of the `DefaultResponseCertification` enum. Or to certify all response headers, with some exclusions, use the `ResponseHeaderExclusions` variant of the `DefaultResponseCertification` enum. Both variants take a [str] slice as an argument. +When certifying a response, the response body and status code are always certified. To additionally certify response headers, use `with_response_certification`. This method takes the `DefaultResponseCertification` enum as an argument. To specify header inclusions, use the `certified_response_headers` function of the `DefaultResponseCertification` enum. Or to certify all response headers, with some exclusions, use the `response_header_exclusions` function of the `DefaultResponseCertification` enum. Both functions take a `str` slice as an argument. #### Fully certified request / response pair @@ -45,7 +45,7 @@ use ic_http_certification::{DefaultCelBuilder, DefaultResponseCertification}; let cel_expr = DefaultCelBuilder::full_certification() .with_request_headers(&["Accept", "Accept-Encoding", "If-Match"]) .with_request_query_parameters(&["foo", "bar", "baz"]) - .with_response_certification(DefaultResponseCertification::CertifiedResponseHeaders(&[ + .with_response_certification(DefaultResponseCertification::certified_response_headers(&[ "Cache-Control", "ETag", ])) @@ -62,7 +62,7 @@ For example, to certify only the request body and method: use ic_http_certification::{DefaultCelBuilder, DefaultResponseCertification}; let cel_expr = DefaultCelBuilder::full_certification() - .with_response_certification(DefaultResponseCertification::CertifiedResponseHeaders(&[ + .with_response_certification(DefaultResponseCertification::certified_response_headers(&[ "Cache-Control", "ETag", ])) @@ -77,7 +77,7 @@ use ic_http_certification::{DefaultCelBuilder, DefaultResponseCertification}; let cel_expr = DefaultCelBuilder::full_certification() .with_request_headers(&[]) .with_request_query_parameters(&[]) - .with_response_certification(DefaultResponseCertification::CertifiedResponseHeaders(&[ + .with_response_certification(DefaultResponseCertification::certified_response_headers(&[ "Cache-Control", "ETag", ])) @@ -92,7 +92,7 @@ Request certification can be skipped entirely by using `DefaultCelBuilder::respo use ic_http_certification::{DefaultCelBuilder, DefaultResponseCertification}; let cel_expr = DefaultCelBuilder::response_certification() - .with_response_certification(DefaultResponseCertification::ResponseHeaderExclusions(&[ + .with_response_certification(DefaultResponseCertification::response_header_exclusions(&[ "Date", "Cookie", "Set-Cookie", @@ -102,7 +102,7 @@ let cel_expr = DefaultCelBuilder::response_certification() #### Partially certified response -Similiarly to request certification, any number of response headers can be provided via the `CertifiedResponseHeaders` variant of the `DefaultResponseCertification` enum when calling `with_response_certification`. The provided array can also be an empty. If the array is empty, or the method is not called, then no response headers will be certified. +Similiarly to request certification, any number of response headers can be provided via the `certified_response_headers` function of the `DefaultResponseCertification` enum when calling `with_response_certification`. The provided array can also be an empty. If the array is empty, or the method is not called, then no response headers will be certified. For example, to certify only the response body and status code: @@ -118,7 +118,7 @@ This can also be done more explicitly: use ic_http_certification::{DefaultCelBuilder, DefaultResponseCertification}; let cel_expr = DefaultCelBuilder::response_certification() - .with_response_certification(DefaultResponseCertification::CertifiedResponseHeaders(&[])) + .with_response_certification(DefaultResponseCertification::certified_response_headers(&[])) .build(); ``` @@ -155,7 +155,7 @@ To define a CEL expression, start with the `CelExpression` enum. This enum provi When certifying requests, the request body and method are always certified. To additionally certify request headers and query parameters, use the `headers` and `query_paramters` of `DefaultRequestCertification` struct. Both properties take a `str` slice as an argument. -When certifying a response, the response body and status code are always certified. To additionally certify response headers, use the `CertifiedResponseHeaders` variant of the `DefaultResponseCertification` enum. Or to certify all response headers, with some exclusions, use the `ResponseHeaderExclusions` variant of the `DefaultResponseCertification` enum. Both variants take a `str` slice as an argument. +When certifying a response, the response body and status code are always certified. To additionally certify response headers, use the `certified_response_headers` function of the `DefaultResponseCertification` enum. Or to certify all response headers, with some exclusions, use the `response_header_exclusions` function of the `DefaultResponseCertification` enum. Both functions take a `str` slice as an argument. Note that the example CEL expressions provided below are formatted for readability. The actual CEL expressions produced by `CelExpression::to_string` and `create_cel_expr` are minified. The minified CEL expression is preferred because it is more compact, resulting in a smaller payload and a faster evaluation time for the HTTP Gateway that is verifying the certification, but the formatted versions are also accepted. @@ -164,14 +164,15 @@ Note that the example CEL expressions provided below are formatted for readabili To define a fully certified request and response pair, including request headers, query parameters, and response headers: ```rust +use std::borrow::Cow; use ic_http_certification::cel::{CelExpression, DefaultCertification, DefaultRequestCertification, DefaultResponseCertification}; let cel_expr = CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &["Accept", "Accept-Encoding", "If-Match"], - query_parameters: &["foo", "bar", "baz"], + headers: Cow::Borrowed(&["Accept", "Accept-Encoding", "If-Match"]), + query_parameters: Cow::Borrowed(&["foo", "bar", "baz"]), }), - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[ + response_certification: DefaultResponseCertification::certified_response_headers(&[ "ETag", "Cache-Control", ]), @@ -206,14 +207,15 @@ Any number of request headers or query parameters can be provided via the `heade For example, to certify only the request body and method: ```rust +use std::borrow::Cow; use ic_http_certification::cel::{CelExpression, DefaultCertification, DefaultRequestCertification, DefaultResponseCertification}; let cel_expr = CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &[], - query_parameters: &[], + headers: Cow::Borrowed(&["Accept", "Accept-Encoding", "If-Match"]), + query_parameters: Cow::Borrowed(&["foo", "bar", "baz"]), }), - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[ + response_certification: DefaultResponseCertification::certified_response_headers(&[ "ETag", "Cache-Control", ]), @@ -250,7 +252,7 @@ use ic_http_certification::cel::{CelExpression, DefaultCertification, DefaultRes let cel_expr = CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: None, - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[ + response_certification: DefaultResponseCertification::certified_response_headers(&[ "ETag", "Cache-Control", ]), @@ -277,17 +279,18 @@ default_certification ( #### Partially certified response -Similiarly to request certification, any number of response headers can be provided via the `CertifiedResponseHeaders` variant of the `DefaultResponseCertification` enum, and it can also be an empty array. If the array is empty, no response headers will be certified. For example: +Similiarly to request certification, any number of response headers can be provided via the `certified_response_headers` variant of the `DefaultResponseCertification` enum, and it can also be an empty array. If the array is empty, no response headers will be certified. For example: ```rust +use std::borrow::Cow; use ic_http_certification::cel::{CelExpression, DefaultCertification, DefaultRequestCertification, DefaultResponseCertification}; let cel_expr = CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &["Accept", "Accept-Encoding", "If-Match"], - query_parameters: &["foo", "bar", "baz"], + headers: Cow::Borrowed(&["Accept", "Accept-Encoding", "If-Match"]), + query_parameters: Cow::Borrowed(&["foo", "bar", "baz"]), }), - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[]), + response_certification: DefaultResponseCertification::certified_response_headers(&[]), })); ``` @@ -309,17 +312,18 @@ default_certification ( ) ``` -If the `ResponseHeaderExclusions` variant is used, an empty array will certify _all_ response headers. For example: +If the `response_header_exclusions` function is used, an empty array will certify _all_ response headers. For example: ```rust +use std::borrow::Cow; use ic_http_certification::cel::{CelExpression, DefaultCertification, DefaultRequestCertification, DefaultResponseCertification}; let cel_expr = CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &["Accept", "Accept-Encoding", "If-Match"], - query_parameters: &["foo", "bar", "baz"], + headers: Cow::Borrowed(&["Accept", "Accept-Encoding", "If-Match"]), + query_parameters: Cow::Borrowed(&["foo", "bar", "baz"]), }), - response_certification: DefaultResponseCertification::ResponseHeaderExclusions(&[]), + response_certification: DefaultResponseCertification::response_header_exclusions(&[]), })); ``` diff --git a/packages/ic-http-certification/src/cel/cel_builder.rs b/packages/ic-http-certification/src/cel/cel_builder.rs index 561ac9dc..0e16bd0f 100644 --- a/packages/ic-http-certification/src/cel/cel_builder.rs +++ b/packages/ic-http-certification/src/cel/cel_builder.rs @@ -1,6 +1,7 @@ use super::{ CelExpression, DefaultCertification, DefaultRequestCertification, DefaultResponseCertification, }; +use std::borrow::Cow; /// A CEL expression builder for creating a default certification expression. #[derive(Debug, Clone)] @@ -104,8 +105,8 @@ impl<'a> DefaultFullCelExpressionBuilder<'a> { /// Build the CEL expression, consuming the builder. pub fn build(self) -> CelExpression<'a> { let request_certification = Some(DefaultRequestCertification { - headers: self.request_headers, - query_parameters: self.request_query_parameters, + headers: Cow::Borrowed(self.request_headers), + query_parameters: Cow::Borrowed(self.request_query_parameters), }); CelExpression::DefaultCertification(Some(DefaultCertification { @@ -131,13 +132,15 @@ mod tests { #[rstest] fn no_request_response_inclusions(no_request_response_inclusions_cel: String) { let cel_expr = DefaultCelBuilder::response_certification() - .with_response_certification(DefaultResponseCertification::CertifiedResponseHeaders(&[ - "Cache-Control", - "ETag", - "Content-Length", - "Content-Type", - "Content-Encoding", - ])) + .with_response_certification(DefaultResponseCertification::certified_response_headers( + &[ + "Cache-Control", + "ETag", + "Content-Length", + "Content-Type", + "Content-Encoding", + ], + )) .build() .to_string(); @@ -147,11 +150,9 @@ mod tests { #[rstest] fn no_request_response_exclusions(no_request_response_exclusions_cel: String) { let cel_expr = DefaultCelBuilder::response_certification() - .with_response_certification(DefaultResponseCertification::ResponseHeaderExclusions(&[ - "Date", - "Cookie", - "Set-Cookie", - ])) + .with_response_certification(DefaultResponseCertification::response_header_exclusions( + &["Date", "Cookie", "Set-Cookie"], + )) .build() .to_string(); @@ -164,9 +165,9 @@ mod tests { .build() .to_string(); let explicit_cel_expr = DefaultCelBuilder::response_certification() - .with_response_certification( - DefaultResponseCertification::CertifiedResponseHeaders(&[]), - ) + .with_response_certification(DefaultResponseCertification::certified_response_headers( + &[], + )) .build() .to_string(); let default_cel_expr = DefaultCelBuilder::response_certification() @@ -182,9 +183,9 @@ mod tests { #[rstest] fn no_request_empty_response_exclusions(no_request_empty_response_exclusions_cel: String) { let cel_expr = DefaultCelBuilder::response_certification() - .with_response_certification( - DefaultResponseCertification::ResponseHeaderExclusions(&[]), - ) + .with_response_certification(DefaultResponseCertification::response_header_exclusions( + &[], + )) .build() .to_string(); @@ -198,13 +199,15 @@ mod tests { let cel_expr = DefaultCelBuilder::full_certification() .with_request_headers(&["Accept", "Accept-Encoding", "If-Match"]) .with_request_query_parameters(&["foo", "bar", "baz"]) - .with_response_certification(DefaultResponseCertification::CertifiedResponseHeaders(&[ - "Cache-Control", - "ETag", - "Content-Length", - "Content-Type", - "Content-Encoding", - ])) + .with_response_certification(DefaultResponseCertification::certified_response_headers( + &[ + "Cache-Control", + "ETag", + "Content-Length", + "Content-Type", + "Content-Encoding", + ], + )) .build() .to_string(); @@ -218,11 +221,9 @@ mod tests { let cel_expr = DefaultCelBuilder::full_certification() .with_request_headers(&["Accept", "Accept-Encoding", "If-Match"]) .with_request_query_parameters(&["foo", "bar", "baz"]) - .with_response_certification(DefaultResponseCertification::ResponseHeaderExclusions(&[ - "Date", - "Cookie", - "Set-Cookie", - ])) + .with_response_certification(DefaultResponseCertification::response_header_exclusions( + &["Date", "Cookie", "Set-Cookie"], + )) .build() .to_string(); @@ -241,9 +242,9 @@ mod tests { let explicit_cel_expr = DefaultCelBuilder::full_certification() .with_request_headers(&["Accept", "Accept-Encoding", "If-Match"]) .with_request_query_parameters(&["foo", "bar", "baz"]) - .with_response_certification( - DefaultResponseCertification::CertifiedResponseHeaders(&[]), - ) + .with_response_certification(DefaultResponseCertification::certified_response_headers( + &[], + )) .build() .to_string(); let default_cel_expr = DefaultCelBuilder::full_certification() @@ -274,9 +275,9 @@ mod tests { let cel_expr = DefaultCelBuilder::full_certification() .with_request_headers(&["Accept", "Accept-Encoding", "If-Match"]) .with_request_query_parameters(&["foo", "bar", "baz"]) - .with_response_certification( - DefaultResponseCertification::ResponseHeaderExclusions(&[]), - ) + .with_response_certification(DefaultResponseCertification::response_header_exclusions( + &[], + )) .build() .to_string(); @@ -289,9 +290,9 @@ mod tests { let explicit_cel_expr = DefaultCelBuilder::full_certification() .with_request_headers(&[]) .with_request_query_parameters(&[]) - .with_response_certification( - DefaultResponseCertification::CertifiedResponseHeaders(&[]), - ) + .with_response_certification(DefaultResponseCertification::certified_response_headers( + &[], + )) .build() .to_string(); let default_cel_expr = DefaultCelBuilder::full_certification() @@ -309,17 +310,17 @@ mod tests { #[rstest] fn empty_request_response_exclusions(empty_request_response_exclusions_cel: String) { let implicit_cel_expr = DefaultCelBuilder::full_certification() - .with_response_certification( - DefaultResponseCertification::ResponseHeaderExclusions(&[]), - ) + .with_response_certification(DefaultResponseCertification::response_header_exclusions( + &[], + )) .build() .to_string(); let explicit_cel_expr = DefaultCelBuilder::full_certification() .with_request_headers(&[]) .with_request_query_parameters(&[]) - .with_response_certification( - DefaultResponseCertification::ResponseHeaderExclusions(&[]), - ) + .with_response_certification(DefaultResponseCertification::response_header_exclusions( + &[], + )) .build() .to_string(); diff --git a/packages/ic-http-certification/src/cel/cel_types.rs b/packages/ic-http-certification/src/cel/cel_types.rs index 65e1543b..8d768a6a 100644 --- a/packages/ic-http-certification/src/cel/cel_types.rs +++ b/packages/ic-http-certification/src/cel/cel_types.rs @@ -1,4 +1,5 @@ use super::create_cel_expr; +use std::borrow::Cow; /// A certification CEL expression defintion. /// Contains an enum variant for each CEL function supported for certification. @@ -53,13 +54,13 @@ pub struct DefaultRequestCertification<'a> { /// /// As many or as little headers can be provided as desired. /// Providing an empty list will result in no request headers being certified. - pub headers: &'a [&'a str], + pub headers: Cow<'a, [&'a str]>, /// A list of request query parameters to include in certification. /// /// As many or as little query parameters can be provided as desired. /// Providing an empty list will result in no request query parameters being certified. - pub query_parameters: &'a [&'a str], + pub query_parameters: Cow<'a, [&'a str]>, } /// Options for configuring certification of a response. @@ -75,17 +76,35 @@ pub enum DefaultResponseCertification<'a> { /// /// As many or as little headers can be provided as desired. /// Providing an empty list will result in no response headers being certified. - CertifiedResponseHeaders(&'a [&'a str]), + CertifiedResponseHeaders(Cow<'a, [&'a str]>), /// A list of response headers to exclude from certification. /// /// As many or as little headers can be provided as desired. /// Providing an empty list will result in all response headers being certified. - ResponseHeaderExclusions(&'a [&'a str]), + ResponseHeaderExclusions(Cow<'a, [&'a str]>), +} + +impl<'a> DefaultResponseCertification<'a> { + /// A list of response headers to include in certification. + /// + /// As many or as little headers can be provided as desired. + /// Providing an empty list will result in no response headers being certified. + pub fn certified_response_headers(headers: &'a [&'a str]) -> Self { + Self::CertifiedResponseHeaders(Cow::Borrowed(headers)) + } + + /// A list of response headers to exclude from certification. + /// + /// As many or as little headers can be provided as desired. + /// Providing an empty list will result in all response headers being certified. + pub fn response_header_exclusions(headers: &'a [&'a str]) -> Self { + Self::ResponseHeaderExclusions(Cow::Borrowed(headers)) + } } impl Default for DefaultResponseCertification<'_> { fn default() -> Self { - DefaultResponseCertification::CertifiedResponseHeaders(&[]) + DefaultResponseCertification::CertifiedResponseHeaders(Cow::Borrowed(&[])) } } diff --git a/packages/ic-http-certification/src/cel/create_cel_expr.rs b/packages/ic-http-certification/src/cel/create_cel_expr.rs index 4a4fc169..eb981cae 100644 --- a/packages/ic-http-certification/src/cel/create_cel_expr.rs +++ b/packages/ic-http-certification/src/cel/create_cel_expr.rs @@ -86,6 +86,7 @@ mod tests { use super::*; use crate::cel::fixtures::*; use rstest::*; + use std::borrow::Cow; #[rstest] #[case::no_certification(no_certification(), no_certification_cel())] @@ -142,7 +143,7 @@ mod tests { fn no_request_response_inclusions() -> CelExpression<'static> { CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: None, - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[ + response_certification: DefaultResponseCertification::certified_response_headers(&[ "Cache-Control", "ETag", "Content-Length", @@ -155,7 +156,7 @@ mod tests { fn no_request_response_exclusions() -> CelExpression<'static> { CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: None, - response_certification: DefaultResponseCertification::ResponseHeaderExclusions(&[ + response_certification: DefaultResponseCertification::response_header_exclusions(&[ "Date", "Cookie", "Set-Cookie", @@ -166,24 +167,24 @@ mod tests { fn no_request_empty_response_inclusions() -> CelExpression<'static> { CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: None, - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[]), + response_certification: DefaultResponseCertification::certified_response_headers(&[]), })) } fn no_request_empty_response_exclusions() -> CelExpression<'static> { CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: None, - response_certification: DefaultResponseCertification::ResponseHeaderExclusions(&[]), + response_certification: DefaultResponseCertification::response_header_exclusions(&[]), })) } fn include_request_response_header_inclusions() -> CelExpression<'static> { CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &["Accept", "Accept-Encoding", "If-Match"], - query_parameters: &["foo", "bar", "baz"], + headers: Cow::Borrowed(&["Accept", "Accept-Encoding", "If-Match"]), + query_parameters: Cow::Borrowed(&["foo", "bar", "baz"]), }), - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[ + response_certification: DefaultResponseCertification::certified_response_headers(&[ "Cache-Control", "ETag", "Content-Length", @@ -196,10 +197,10 @@ mod tests { fn include_request_response_header_exclusions() -> CelExpression<'static> { CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &["Accept", "Accept-Encoding", "If-Match"], - query_parameters: &["foo", "bar", "baz"], + headers: Cow::Borrowed(&["Accept", "Accept-Encoding", "If-Match"]), + query_parameters: Cow::Borrowed(&["foo", "bar", "baz"]), }), - response_certification: DefaultResponseCertification::ResponseHeaderExclusions(&[ + response_certification: DefaultResponseCertification::response_header_exclusions(&[ "Date", "Cookie", "Set-Cookie", @@ -210,40 +211,40 @@ mod tests { fn include_request_empty_response_inclusions() -> CelExpression<'static> { CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &["Accept", "Accept-Encoding", "If-Match"], - query_parameters: &["foo", "bar", "baz"], + headers: Cow::Borrowed(&["Accept", "Accept-Encoding", "If-Match"]), + query_parameters: Cow::Borrowed(&["foo", "bar", "baz"]), }), - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[]), + response_certification: DefaultResponseCertification::certified_response_headers(&[]), })) } fn include_request_empty_response_exclusions() -> CelExpression<'static> { CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &["Accept", "Accept-Encoding", "If-Match"], - query_parameters: &["foo", "bar", "baz"], + headers: Cow::Borrowed(&["Accept", "Accept-Encoding", "If-Match"]), + query_parameters: Cow::Borrowed(&["foo", "bar", "baz"]), }), - response_certification: DefaultResponseCertification::ResponseHeaderExclusions(&[]), + response_certification: DefaultResponseCertification::response_header_exclusions(&[]), })) } fn empty_request_response_inclusions() -> CelExpression<'static> { CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &[], - query_parameters: &[], + headers: Cow::Borrowed(&[]), + query_parameters: Cow::Borrowed(&[]), }), - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[]), + response_certification: DefaultResponseCertification::certified_response_headers(&[]), })) } fn empty_request_response_exclusions() -> CelExpression<'static> { CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &[], - query_parameters: &[], + headers: Cow::Borrowed(&[]), + query_parameters: Cow::Borrowed(&[]), }), - response_certification: DefaultResponseCertification::ResponseHeaderExclusions(&[]), + response_certification: DefaultResponseCertification::response_header_exclusions(&[]), })) } } diff --git a/packages/ic-http-certification/src/lib.rs b/packages/ic-http-certification/src/lib.rs index ac9d547a..f6803a6d 100644 --- a/packages/ic-http-certification/src/lib.rs +++ b/packages/ic-http-certification/src/lib.rs @@ -34,7 +34,7 @@ The CEL builder interface is provided to ease the creation of CEL expressions th When certifying requests, the request body and method are always certified. To additionally certify request headers and query parameters, use [with_request_headers](cel::DefaultFullCelExpressionBuilder::with_request_headers()) and [with_request_query_parameters](cel::DefaultFullCelExpressionBuilder::with_request_query_parameters()) respectively. Both methods take a [str] slice as an argument. -When certifying a response, the response body and status code are always certified. To additionally certify response headers, use [with_response_certification](cel::DefaultFullCelExpressionBuilder::with_response_certification()). This method takes the [DefaultResponseCertification](DefaultResponseCertification) enum as an argument. To specify header inclusions, use the [CertifiedResponseHeaders](DefaultResponseCertification::CertifiedResponseHeaders) variant of the [DefaultResponseCertification](DefaultResponseCertification) enum. Or to certify all response headers, with some exclusions, use the [ResponseHeaderExclusions](DefaultResponseCertification::ResponseHeaderExclusions) variant of the [DefaultResponseCertification](DefaultResponseCertification) enum. Both variants take a [str] slice as an argument. +When certifying a response, the response body and status code are always certified. To additionally certify response headers, use [with_response_certification](cel::DefaultFullCelExpressionBuilder::with_response_certification()). This method takes the [DefaultResponseCertification](DefaultResponseCertification) enum as an argument. To specify header inclusions, use the [certified_response_headers](DefaultResponseCertification::certified_response_headers) function of the [DefaultResponseCertification](DefaultResponseCertification) enum. Or to certify all response headers, with some exclusions, use the [response_header_exclusions](DefaultResponseCertification::response_header_exclusions) function of the [DefaultResponseCertification](DefaultResponseCertification) enum. Both functions take a [str] slice as an argument. #### Fully certified request / response pair @@ -46,7 +46,7 @@ use ic_http_certification::{DefaultCelBuilder, DefaultResponseCertification}; let cel_expr = DefaultCelBuilder::full_certification() .with_request_headers(&["Accept", "Accept-Encoding", "If-Match"]) .with_request_query_parameters(&["foo", "bar", "baz"]) - .with_response_certification(DefaultResponseCertification::CertifiedResponseHeaders(&[ + .with_response_certification(DefaultResponseCertification::certified_response_headers(&[ "Cache-Control", "ETag", ])) @@ -63,7 +63,7 @@ For example, to certify only the request body and method: use ic_http_certification::{DefaultCelBuilder, DefaultResponseCertification}; let cel_expr = DefaultCelBuilder::full_certification() - .with_response_certification(DefaultResponseCertification::CertifiedResponseHeaders(&[ + .with_response_certification(DefaultResponseCertification::certified_response_headers(&[ "Cache-Control", "ETag", ])) @@ -78,7 +78,7 @@ use ic_http_certification::{DefaultCelBuilder, DefaultResponseCertification}; let cel_expr = DefaultCelBuilder::full_certification() .with_request_headers(&[]) .with_request_query_parameters(&[]) - .with_response_certification(DefaultResponseCertification::CertifiedResponseHeaders(&[ + .with_response_certification(DefaultResponseCertification::certified_response_headers(&[ "Cache-Control", "ETag", ])) @@ -93,7 +93,7 @@ Request certification can be skipped entirely by using [DefaultCelBuilder::respo use ic_http_certification::{DefaultCelBuilder, DefaultResponseCertification}; let cel_expr = DefaultCelBuilder::response_certification() - .with_response_certification(DefaultResponseCertification::ResponseHeaderExclusions(&[ + .with_response_certification(DefaultResponseCertification::response_header_exclusions(&[ "Date", "Cookie", "Set-Cookie", @@ -103,7 +103,7 @@ let cel_expr = DefaultCelBuilder::response_certification() #### Partially certified response -Similiarly to request certification, any number of response headers can be provided via the [CertifiedResponseHeaders](DefaultResponseCertification::CertifiedResponseHeaders) variant of the [DefaultResponseCertification](DefaultResponseCertification) enum when calling [with_response_certification](cel::DefaultFullCelExpressionBuilder::with_response_certification()). The provided array can also be an empty. If the array is empty, or the method is not called, then no response headers will be certified. +Similiarly to request certification, any number of response headers can be provided via the [certified_response_headers](DefaultResponseCertification::certified_response_headers) function of the [DefaultResponseCertification](DefaultResponseCertification) enum when calling [with_response_certification](cel::DefaultFullCelExpressionBuilder::with_response_certification()). The provided array can also be an empty. If the array is empty, or the method is not called, then no response headers will be certified. For example, to certify only the response body and status code: @@ -120,7 +120,7 @@ This can also be done more explicitly: use ic_http_certification::{DefaultCelBuilder, DefaultResponseCertification}; let cel_expr = DefaultCelBuilder::response_certification() - .with_response_certification(DefaultResponseCertification::CertifiedResponseHeaders(&[])) + .with_response_certification(DefaultResponseCertification::certified_response_headers(&[])) .build(); ``` @@ -157,7 +157,7 @@ To define a CEL expression, start with the [CelExpression](cel::CelExpression) e When certifying requests, the request body and method are always certified. To additionally certify request headers and query parameters, use the [headers](cel::DefaultRequestCertification::headers) and [query_parameters](cel::DefaultRequestCertification::query_parameters) of [DefaultRequestCertification](cel::DefaultRequestCertification) struct. Both properties take a [str] slice as an argument. -When certifying a response, the response body and status code are always certified. To additionally certify response headers, use the [CertifiedResponseHeaders](DefaultResponseCertification::CertifiedResponseHeaders) variant of the [DefaultResponseCertification](DefaultResponseCertification) enum. Or to certify all response headers, with some exclusions, use the [ResponseHeaderExclusions](DefaultResponseCertification::ResponseHeaderExclusions) variant of the [DefaultResponseCertification](DefaultResponseCertification) enum. Both variants take a [str] slice as an argument. +When certifying a response, the response body and status code are always certified. To additionally certify response headers, use the [certified_response_headers](DefaultResponseCertification::certified_response_headers) function of the [DefaultResponseCertification](DefaultResponseCertification) enum. Or to certify all response headers, with some exclusions, use the [response_header_exclusions](DefaultResponseCertification::response_header_exclusions) function of the [DefaultResponseCertification](DefaultResponseCertification) enum. Both functions take a [str] slice as an argument. Note that the example CEL expressions provided below are formatted for readability. The actual CEL expressions produced by [CelExpression::to_string](cel::CelExpression::to_string()) and [create_cel_expr](cel::create_cel_expr()) are minified. The minified CEL expression is preferred because it is more compact, resulting in a smaller payload and a faster evaluation time for the HTTP Gateway that is verifying the certification, but the formatted versions are also accepted. @@ -166,14 +166,15 @@ Note that the example CEL expressions provided below are formatted for readabili To define a fully certified request and response pair, including request headers, query parameters, and response headers: ```rust +use std::borrow::Cow; use ic_http_certification::cel::{CelExpression, DefaultCertification, DefaultRequestCertification, DefaultResponseCertification}; let cel_expr = CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &["Accept", "Accept-Encoding", "If-Match"], - query_parameters: &["foo", "bar", "baz"], + headers: Cow::Borrowed(&["Accept", "Accept-Encoding", "If-Match"]), + query_parameters: Cow::Borrowed(&["foo", "bar", "baz"]), }), - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[ + response_certification: DefaultResponseCertification::certified_response_headers(&[ "ETag", "Cache-Control", ]), @@ -208,14 +209,15 @@ Any number of request headers or query parameters can be provided via the [heade For example, to certify only the request body and method: ```rust +use std::borrow::Cow; use ic_http_certification::cel::{CelExpression, DefaultCertification, DefaultRequestCertification, DefaultResponseCertification}; let cel_expr = CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &[], - query_parameters: &[], + headers: Cow::Borrowed(&["Accept", "Accept-Encoding", "If-Match"]), + query_parameters: Cow::Borrowed(&["foo", "bar", "baz"]), }), - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[ + response_certification: DefaultResponseCertification::certified_response_headers(&[ "ETag", "Cache-Control", ]), @@ -252,7 +254,7 @@ use ic_http_certification::cel::{CelExpression, DefaultCertification, DefaultRes let cel_expr = CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: None, - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[ + response_certification: DefaultResponseCertification::certified_response_headers(&[ "ETag", "Cache-Control", ]), @@ -279,17 +281,18 @@ default_certification ( #### Partially certified response -Similiarly to request certification, any number of response headers can be provided via the [CertifiedResponseHeaders](DefaultResponseCertification::CertifiedResponseHeaders) variant of the [DefaultResponseCertification](DefaultResponseCertification) enum, and it can also be an empty array. If the array is empty, no response headers will be certified. For example: +Similiarly to request certification, any number of response headers can be provided via the [certified_response_headers](DefaultResponseCertification::certified_response_headers) function of the [DefaultResponseCertification](DefaultResponseCertification) enum, and it can also be an empty array. If the array is empty, no response headers will be certified. For example: ```rust +use std::borrow::Cow; use ic_http_certification::cel::{CelExpression, DefaultCertification, DefaultRequestCertification, DefaultResponseCertification}; let cel_expr = CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &["Accept", "Accept-Encoding", "If-Match"], - query_parameters: &["foo", "bar", "baz"], + headers: Cow::Borrowed(&["Accept", "Accept-Encoding", "If-Match"]), + query_parameters: Cow::Borrowed(&["foo", "bar", "baz"]), }), - response_certification: DefaultResponseCertification::CertifiedResponseHeaders(&[]), + response_certification: DefaultResponseCertification::certified_response_headers(&[]), })); ``` @@ -311,17 +314,18 @@ default_certification ( ) ``` -If the [ResponseHeaderExclusions](DefaultResponseCertification::ResponseHeaderExclusions) variant is used, an empty array will certify _all_ response headers. For example: +If the [response_header_exclusions](DefaultResponseCertification::response_header_exclusions) funciton is used, an empty array will certify _all_ response headers. For example: ```rust +use std::borrow::Cow; use ic_http_certification::cel::{CelExpression, DefaultCertification, DefaultRequestCertification, DefaultResponseCertification}; let cel_expr = CelExpression::DefaultCertification(Some(DefaultCertification { request_certification: Some(DefaultRequestCertification { - headers: &["Accept", "Accept-Encoding", "If-Match"], - query_parameters: &["foo", "bar", "baz"], + headers: Cow::Borrowed(&["Accept", "Accept-Encoding", "If-Match"]), + query_parameters: Cow::Borrowed(&["foo", "bar", "baz"]), }), - response_certification: DefaultResponseCertification::ResponseHeaderExclusions(&[]), + response_certification: DefaultResponseCertification::response_header_exclusions(&[]), })); ```