iliana / rust-crowbar

Wrapper to simplify writing AWS Lambda functions in Rust (using the Python execution environment)
https://docs.rs/crowbar
Apache License 2.0
197 stars 16 forks source link

Convert Lambda Proxy Integration events to specialized objects #2

Closed iliana closed 6 years ago

iliana commented 7 years ago

Lambda Proxy Integration is a really nifty system that allows the Lambda function to view all details of a request via API Gateway and return an object representing a fuller HTTP response (status code, additional headers, ...).

Since we might want to use another crate's structs/traits, this should probably be behind a feature gate to make the dependency optional.

There are two ways we might do this. Perhaps we should do both.

First, we could have the function accept an object implementing a Handler trait. This has the advantage of easily allowing developers to convert an existing server implementation in hyper to an API Gateway + Lambda + crowbar stack, but masks the Lambda context object from use.

Second, we could require a function signature that takes Request and LambdaContext objects and returns a Response object. The advantages/disadvantages are generally opposite the other option.

I first looked at reusing hyper's Request and Response objects but they use lower-level information than what we have in the Lambda event. iron's objects may be a better fit. I'm not sure if we should rely on another crate's structs since some new future features may require creating objects with information we don't have.

iliana commented 7 years ago

conduit's interfaces look really good...

iliana commented 7 years ago

Dropping the milestone as I'm still not comfortable enough with committing to a single crate's interfaces for 0.2.0, and I don't want to work on multiple interfaces at the moment.

iliana commented 7 years ago

https://crates.io/crates/http/ just came out and looks like a great interface for this.

nbigaouette-eai commented 6 years ago

I've built a Lambda in Rust (thanks to crowbar!) and deployed it manually as a proof of concept. It seems that the way I created my API gateway for this experiment did not set up a Lambda Proxy. As such, I was not receiving the full HTTP request and I could simply return the serde_json::Value.

After this proof of concept, I've used serverless to deploy but unfortunately my requests were not going through. Logs revealed that that I was receiving the full HTTP request in the lambda and my attempt at deserializing it was failing. I've learned later that this was caused by serverless using a Lambda Proxy by default:

The Framework uses the lambda-proxy method (i.e., everything is passed into your Lambda) by default unless another method is supplied by the user

I thus fixed my deserialization to work on the body part of the event. But now what turns out to be the proxy does not understand my LambdaResult and curling my API gives me {"message": "Internal server error"}.

Is there a way that I can add explicitly an http::StatusCode::OK so that the Proxy can send me back the result? If not, what would need to be changed to crowbar to support this?

Thanks!

iliana commented 6 years ago

That's what this issue is tracking development of -- a variant of lambda! or a wrapper that unpacks the Lambda Proxy request object into a http::Request, and then repacking a http::Response into the JSON object that API Gateway expects.

In the meantime, returning a serde_json structure that looks like what API Gateway expects should work for you.

nbigaouette-eai commented 6 years ago

Yeah, that's what I've figured... I'm building this json manually (from the link you gave):

{
    "statusCode": 200,
    "body": [...]
}

That adds quite some boilerplate though. I'll be sure to follow any changes being made to use the http crate! Thanks!

nbigaouette-eai commented 6 years ago

Just a note for other passerby... The body that must returned as mention in my previous comment must be a string, not a json value! Else the Proxy will not understand and curling will fail (while a manual test in the lambda management console would succeed).

So for example, return this:

Ok(json!({
    "statusCode": 200,
    "body": "{ \"example\": \"data\", \"to_return\": 2 }"
}))

Not this:

Ok(json!({
    "statusCode": 200,
    "body": {
        "example": "data",
        "to_return": 2
    }
}))
iliana commented 6 years ago

This miiiight be superseded by #32 -- does that seem correct, @naftulikay?

naftulikay commented 6 years ago

Yes, it will be superseded by #32.

softprops commented 6 years ago

I've published a crate that builds on crowbars foundation with an emphasis on API gateway and the std http crates interfaces https://github.com/softprops/lando

iliana commented 6 years ago

I'm going to close this, and I think it's worth pushing people who want to use Rust with API Gateway to use lando. ^_^