From b3b522a1fbc811a8de4c2266b8a1e41fc86bec5b Mon Sep 17 00:00:00 2001 From: Daniel Cormier Date: Fri, 17 Feb 2023 15:50:04 -0500 Subject: [PATCH 1/2] Fixed some types in docs and tests --- lambda-http/src/ext.rs | 8 ++++---- lambda-http/src/request.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lambda-http/src/ext.rs b/lambda-http/src/ext.rs index 09551d0e..3c72ac6a 100644 --- a/lambda-http/src/ext.rs +++ b/lambda-http/src/ext.rs @@ -55,7 +55,7 @@ impl Error for PayloadError { } } -/// Extentions for `lambda_http::Request` structs that +/// Extensions for `lambda_http::Request` structs that /// provide access to [API gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format) /// and [ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html) /// features. @@ -358,7 +358,7 @@ mod tests { } #[test] - fn requests_have_json_parseable_payloads() { + fn requests_have_json_parsable_payloads() { #[derive(Deserialize, Eq, PartialEq, Debug)] struct Payload { foo: String, @@ -421,7 +421,7 @@ mod tests { } #[test] - fn requests_omiting_content_types_do_not_support_parseable_payloads() { + fn requests_omitting_content_types_do_not_support_parsable_payloads() { #[derive(Deserialize, Eq, PartialEq, Debug)] struct Payload { foo: String, @@ -429,7 +429,7 @@ mod tests { } let request = http::Request::builder() .body(Body::from(r#"{"foo":"bar", "baz": 2}"#)) - .expect("failed to bulid request"); + .expect("failed to build request"); let payload: Option = request.payload().unwrap_or_default(); assert_eq!(payload, None); } diff --git a/lambda-http/src/request.rs b/lambda-http/src/request.rs index 95cf6a52..c31398c5 100644 --- a/lambda-http/src/request.rs +++ b/lambda-http/src/request.rs @@ -298,7 +298,7 @@ fn into_websocket_request(ag: ApiGatewayWebsocketProxyRequest) -> http::Request< .extension(RequestContext::WebSocket(ag.request_context)); // merge headers into multi_value_headers and make - // multi-value_headers our cannoncial source of request headers + // multi-value_headers our canonical source of request headers let mut headers = ag.multi_value_headers; headers.extend(ag.headers); update_xray_trace_id_header(&mut headers); From 8cea97e08bfeb9fbc98293e3087de97d53dd203c Mon Sep 17 00:00:00 2001 From: Daniel Cormier Date: Fri, 17 Feb 2023 16:03:53 -0500 Subject: [PATCH 2/2] Add convenience methods to get references to data in the request There are existing methods to get owned clones of various pieces of data in the `Request`. This adds methods to get references where owned data is not needed. --- lambda-http/src/ext.rs | 115 ++++++++++++++++++++++++++++++++++------- 1 file changed, 95 insertions(+), 20 deletions(-) diff --git a/lambda-http/src/ext.rs b/lambda-http/src/ext.rs index 3c72ac6a..f034c686 100644 --- a/lambda-http/src/ext.rs +++ b/lambda-http/src/ext.rs @@ -109,6 +109,9 @@ pub trait RequestExt { /// Return the raw http path for a request without any stage information. fn raw_http_path(&self) -> String; + /// Return the raw http path for a request without any stage information. + fn raw_http_path_str(&self) -> &str; + /// Configures instance with the raw http path. fn with_raw_http_path(self, path: &str) -> Self; @@ -118,12 +121,24 @@ pub trait RequestExt { /// /// The yielded value represents both single and multi-valued /// parameters alike. When multiple query string parameters with the same - /// name are expected, `query_string_parameters().get_all("many")` to retrieve them all. + /// name are expected, `query_string_parameters().all("many")` to retrieve them all. /// - /// No query parameters - /// will yield an empty `QueryMap`. + /// No query parameters will yield an empty `QueryMap`. fn query_string_parameters(&self) -> QueryMap; + /// Return pre-parsed http query string parameters, parameters + /// provided after the `?` portion of a url, + /// associated with the API gateway request. + /// + /// The yielded value represents both single and multi-valued + /// parameters alike. When multiple query string parameters with the same + /// name are expected, + /// `query_string_parameters_ref().and_then(|params| params.all("many"))` to + /// retrieve them all. + /// + /// No query parameters will yield `None`. + fn query_string_parameters_ref(&self) -> Option<&QueryMap>; + /// Configures instance with query string parameters /// /// This is intended for use in mock testing contexts. @@ -139,6 +154,14 @@ pub trait RequestExt { /// These will always be empty for ALB triggered requests fn path_parameters(&self) -> QueryMap; + /// Return pre-extracted path parameters, parameter provided in url placeholders + /// `/foo/{bar}/baz/{boom}`, + /// associated with the API gateway request. No path parameters + /// will yield `None` + /// + /// These will always be `None` for ALB triggered requests + fn path_parameters_ref(&self) -> Option<&QueryMap>; + /// Configures instance with path parameters /// /// This is intended for use in mock testing contexts. @@ -153,6 +176,13 @@ pub trait RequestExt { /// These will always be empty for ALB triggered requests fn stage_variables(&self) -> QueryMap; + /// Return [stage variables](https://docs.aws.amazon.com/apigateway/latest/developerguide/stage-variables.html) + /// associated with the API gateway request. No stage parameters + /// will yield `None` + /// + /// These will always be `None` for ALB triggered requests + fn stage_variables_ref(&self) -> Option<&QueryMap>; + /// Configures instance with stage variables under #[cfg(test)] configurations /// /// This is intended for use in mock testing contexts. @@ -164,6 +194,10 @@ pub trait RequestExt { /// Return request context data associated with the ALB or API gateway request fn request_context(&self) -> RequestContext; + /// Return a reference to the request context data associated with the ALB or + /// API gateway request + fn request_context_ref(&self) -> Option<&RequestContext>; + /// Configures instance with request context /// /// This is intended for use in mock testing contexts. @@ -185,15 +219,23 @@ pub trait RequestExt { /// Return the Lambda function context associated with the request fn lambda_context(&self) -> Context; + /// Return a reference to the the Lambda function context associated with the + /// request + fn lambda_context_ref(&self) -> Option<&Context>; + /// Configures instance with lambda context fn with_lambda_context(self, context: Context) -> Self; } impl RequestExt for http::Request { fn raw_http_path(&self) -> String { + self.raw_http_path_str().to_string() + } + + fn raw_http_path_str(&self) -> &str { self.extensions() .get::() - .map(|ext| ext.0.clone()) + .map(|RawHttpPath(path)| path.as_str()) .unwrap_or_default() } @@ -204,10 +246,19 @@ impl RequestExt for http::Request { } fn query_string_parameters(&self) -> QueryMap { - self.extensions() - .get::() - .map(|ext| ext.0.clone()) - .unwrap_or_default() + self.query_string_parameters_ref().cloned().unwrap_or_default() + } + + fn query_string_parameters_ref(&self) -> Option<&QueryMap> { + self.extensions().get::().and_then( + |QueryStringParameters(params)| { + if params.is_empty() { + None + } else { + Some(params) + } + }, + ) } fn with_query_string_parameters(self, parameters: Q) -> Self @@ -220,10 +271,19 @@ impl RequestExt for http::Request { } fn path_parameters(&self) -> QueryMap { - self.extensions() - .get::() - .map(|ext| ext.0.clone()) - .unwrap_or_default() + self.path_parameters_ref().cloned().unwrap_or_default() + } + + fn path_parameters_ref(&self) -> Option<&QueryMap> { + self.extensions().get::().and_then( + |PathParameters(params)| { + if params.is_empty() { + None + } else { + Some(params) + } + }, + ) } fn with_path_parameters

(self, parameters: P) -> Self @@ -236,10 +296,19 @@ impl RequestExt for http::Request { } fn stage_variables(&self) -> QueryMap { - self.extensions() - .get::() - .map(|ext| ext.0.clone()) - .unwrap_or_default() + self.stage_variables_ref().cloned().unwrap_or_default() + } + + fn stage_variables_ref(&self) -> Option<&QueryMap> { + self.extensions().get::().and_then( + |StageVariables(vars)| { + if vars.is_empty() { + None + } else { + Some(vars) + } + }, + ) } #[cfg(test)] @@ -253,12 +322,15 @@ impl RequestExt for http::Request { } fn request_context(&self) -> RequestContext { - self.extensions() - .get::() + self.request_context_ref() .cloned() .expect("Request did not contain a request context") } + fn request_context_ref(&self) -> Option<&RequestContext> { + self.extensions().get::() + } + fn with_request_context(self, context: RequestContext) -> Self { let mut s = self; s.extensions_mut().insert(context); @@ -266,12 +338,15 @@ impl RequestExt for http::Request { } fn lambda_context(&self) -> Context { - self.extensions() - .get::() + self.lambda_context_ref() .cloned() .expect("Request did not contain a lambda context") } + fn lambda_context_ref(&self) -> Option<&Context> { + self.extensions().get::() + } + fn with_lambda_context(self, context: Context) -> Self { let mut s = self; s.extensions_mut().insert(context);