Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support for server lambda_http::Request #1551

Merged
merged 18 commits into from
Aug 19, 2022

Conversation

hugobast
Copy link
Contributor

@hugobast hugobast commented Jul 16, 2022

Motivation and Context

This PR replaces: #1338

Adds support for accepting lambda_http::Request.

Testing

Pokemon Service is updated with a lambda_http run example.

Checklist

  • I have updated CHANGELOG.next.toml if I made changes to the smithy-rs codegen or runtime crates
  • I have updated CHANGELOG.next.toml if I made changes to the AWS SDK, generated SDK code, or SDK runtime crates

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@hugobast hugobast requested a review from a team as a code owner July 16, 2022 02:57
@Velfi Velfi added the server Rust server SDK label Jul 18, 2022
@hugobast hugobast changed the title feat: support for request lambda_http::Body feat: support for router with lambda_http::Body Jul 19, 2022
Copy link
Contributor

@crisidev crisidev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Do you mind to fix the conflict so we can merge.

Copy link
Contributor

@david-perez david-perez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry it took me so long to take a look at this, I was on holiday.

I believe the last thing that stands in the way is #1364

#1364 is unrelated to this change. What this change does is to allow smithy-rs to take in lambda_http:Requests as input, by adding a converter from Lambda's body error type into a smithy-rs RequestRejection. This will get returned when we fail to buffer non-streaming requests as bytes. You might want to update the PR description / commit message to better reflect the intent of this patch.

I could use some help devising a test; the way I've tested this is by changing the pokemon service to use lambda_http::run in this fashion and witnessing that the code compiles:

It'd be nice if we could showcase a working Lambda in the repo as an example project. #1338 includes a nice example you can copy over. You'll also need to copy over the stage stripping part from the request URI path. Do you want to tackle this in a separate PR?

I am unsure what to put under the CHANGELOG for this change; please advise.

A simple message along the lines of "Add support for accepting input lambda_http::Requests in the server" will do.


Thank you!

rust-runtime/aws-smithy-http-server/src/rejection.rs Outdated Show resolved Hide resolved
@hugobast
Copy link
Contributor Author

Sorry it took me so long to take a look at this, I was on holiday.

I'm currently taking a week off too, I'll get to this on Monday. Thanks!

@hugobast
Copy link
Contributor Author

👋 Back dusting this off and see if I can finish the last leg

#1364 is unrelated to this change. What this change does is to allow smithy-rs to take in lambda_http:Requests as input, by adding a converter from Lambda's body error type into a smithy-rs RequestRejection. This will get returned when we fail to buffer non-streaming requests as bytes. You might want to update the PR description / commit message to better reflect the intent of this patch.

I probably had the wrong thing to paste here; I believe I intended to link to this comment: #1338 (comment) which had a comment about a workaround to #1364. Sorry for the confusion.

You'll also need to copy over the stage stripping part from the request URI path. Do you want to tackle this in a separate PR?

I'd like to get this all done in this PR, so I'll update accordingly,

Thanks for the feedback!

@hugobast hugobast requested a review from a team as a code owner August 17, 2022 01:41
@hugobast hugobast changed the title feat: support for router with lambda_http::Body feat: support for server lambda_http::Request Aug 17, 2022
Copy link
Contributor

@david-perez david-perez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Do you want to copy over Eduardo's cargo lambda config (see rust-runtime/aws-smithy-http-server/examples/{Makefile, README.md} in his PR). It would run the new Lambda executable example.

Can you also update the CHANGELOG.next.toml saying that there is now a canonical and easy way to run smithy-rs on Lambda, linking to the example? We have users doing the old request-response mapping + HTTP URI path stage stripping in their applications, and they'll be happy to know they can get rid of them. Call out in the changelog that there are now converters between SdkBody and lambda_http::Body.

@david-perez
Copy link
Contributor

In your Lambdas, how are you handling usage of the Lambda context in your operation handlers? It's useful for X-Ray integration, logging a request ID etc.

Our users currently have to retrieve it out of the lambda_http::Request and insert it into the HTTP extensions with their state. It's not a great UX. I was wondering if you had any ideas to make it better.

@hugobast
Copy link
Contributor Author

hugobast commented Aug 17, 2022

New information

You'll also need to copy over the stage stripping part from the request URI path. Do you want to tackle this in a separate PR?

I had to do some research yesterday since stage stripping wasn't giving me the expected result. It turns out that as implemented in #1338 we were not stripping anything.

let raw_path = request.raw_http_path()
/// raw_path = "" (empty)

The routing worked at a specific version (sha: eduardomourar@e05b302) because of how the server initializes RequestSpec regexes.

Example:

uri_path_regex: /orders/123/shipments$

It's subtle but it lacks the start of line assert ^ which is present in current versions of smithy-rs. That old regex will match a path like this /prod/orders/123/shipments and more relevant for me it will match a versioned path like this /prod/2022-01-01/orders/123/shipments.

The new regexes look like this:

uri_path_regex: ^/orders/123/shipments$

After stage stripping it will still not match the versioned path that I have /2022-01-01/orders/123/shipments.

I'm not sure what to do about stripping /2022-01-01 if any of this sparks a thought for anyone reading please let me know.

Edit

@david-perez thanks for the review, will work through it today. How are other users dealing with having versioning in their path?

Are they adding the version to the path like so?

@http(uri: "/2022-01-01/orders", method: "POST")
operation CreateOrder {
...
}

Copy link
Collaborator

@rcoh rcoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we'll need to figure out how to make this work without adding an unconditional lambda dependency to aws-smithy-http

rust-runtime/aws-smithy-http/src/body.rs Outdated Show resolved Hide resolved
rust-runtime/aws-smithy-http/src/byte_stream.rs Outdated Show resolved Hide resolved
@hugobast
Copy link
Contributor Author

hugobast commented Aug 17, 2022

@david-perez

In your Lambdas, how are you handling usage of the Lambda context in your operation handlers? It's useful for X-Ray integration, logging a request ID etc.

Our users currently have to retrieve it out of the lambda_http::Request and insert it into the HTTP extensions with their state. It's not a great UX. I was wondering if you had any ideas to make it better.

I've asked a team member about this; I don't think we do anything with the Lambda context yet. I wasn't involved with our X-Ray integration, but I know we have one, and it works.

Maybe this is related, for things like extensions on Request, we've made a RequestExt trait like this:

pub trait RequestExt {
    fn account_id(&self) -> Option<&str>;
    fn request_id(&self) -> Option<&str>;
}

And Request<T> implements RequestExt.

Copy link
Collaborator

@rcoh rcoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm from my side thanks!!

@david-perez
Copy link
Contributor

@david-perez thanks for the review, will work through it today. How are other users dealing with having versioning in their path?

Is the version an API Gateway stage? If so, they are stripping it using a similar function than convert_event from this PR, applying it as middleware. The Smithy model does not include the stage in the URI, since it's deployed to multiple stages.

@hugobast
Copy link
Contributor Author

At what point in the request lifecycle do you get to use the account_id and request_id methods? Do you thread those strings to the operation handler functions? If yes, how?

Oh right, no, we don't have those in our operation handlers; sorry to mislead, they are only available in middlewares (layers/services)

@hugobast
Copy link
Contributor Author

hugobast and others added 13 commits August 18, 2022 15:01
This refactor is to address multiple pull request review comments
1. Removes the hard dependency between lambda_http and aws-smithy-http
2. Replaces the false MakeService with a Service handler instead, this
   is terminology that lambda_http::run already uses and should make it
   explicit to user that a handler like this is needed to convert lambda
   events to hyper requests
3. Updates the pokemon service example
@david-perez david-perez enabled auto-merge (squash) August 19, 2022 09:14
CHANGELOG.next.toml Outdated Show resolved Hide resolved
CHANGELOG.next.toml Outdated Show resolved Hide resolved
@david-perez david-perez enabled auto-merge (squash) August 19, 2022 09:40
@david-perez david-perez merged commit 9ee45bf into smithy-lang:main Aug 19, 2022
@david-perez
Copy link
Contributor

@hugobast Thanks for your contribution.

Changes were made in order to avoid doing a body conversion from a lambda_http::Body to a hyper::Body it's unfortunate that we would have to do a body conversion here anyway for ByteStream?

We will try to address this, perhaps via #1125, so that convert_event does not have to make the body type conversion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
server Rust server SDK
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants