crystal-aws-lambda icon indicating copy to clipboard operation
crystal-aws-lambda copied to clipboard

Experiment converting JSON::Aany to string

Open dyslexic-degenerate opened this issue 4 years ago • 0 comments

Hey @spinscale,

I've been using your project to work on a serverless lambda project. Thanks!

I'm bumping into an issue and figured I'd open a pull request to explore some options.

The issue:

The current Lambda::Builder::HTTPRequest class doesn't support AWS HTTP ApiGateway's request structure (https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api.html)

In the pull request I put an example spec 'parses api gateway v2 (HTTP gateway)' that is failing to parse.

Idea 1)

I like the idea behind supplying Lambda::Builder::HTTPRequest... I think overall it may be a bit limitting.

An alternative approach I'm thinking through is to leverage JSON serializable event objects that can be used to handle a wide range of lambda request structures.

I come from a go backgroung and this is the approach that aws takes there. For example here are all the event definitions: https://github.com/aws/aws-lambda-go/blob/5d6413264f82afaa7587b56e3f09f1422c898c68/events/apigw.go#L6

An example class would look like:

module AWSLambdaCrystal::Events
  class APIGatewayV2HTTPResponse
    include JSON::Serializable

    @[JSON::Field(key: "statusCode")]
    property status_code : Int32

    @[JSON::Field(key: "headers")]
    property headers : Hash(String, String)

    @[JSON::Field(key: "multiValueHeaders")]
    property headers : Hash(String, Array(String))

    @[JSON::Field(key: "body")]
    property body : String

    @[JSON::Field(key: "body")]
    property is_base64_encoded : Bool?

    @[JSON::Field(key: "cookies")]
    property cookies : Array(String)
  end
end

In the case of go the handler will automatically serialize the incoming json into the appropriate type connected to the handler: https://github.com/aws/aws-lambda-go/blob/5d6413264f82afaa7587b56e3f09f1422c898c68/lambda/handler.go#L83

I kinda like that approach.

That approach also still leaves open the Lambda::Builder::HTTPRequest concept where you make the api gateway request look like an HTTP request.

In order to gain that same benefit you can instead construct Lambda::Builder::HTTPRequest from one of the serialized classes.

Api Gateway Json => Serialized to event object of appropriate type => Lambda::Builder::HTTPRequest (in the case of the api gateway events).

I'm still playing with this idea and trying to make it have a good feel to it wrt connecting the handler...

Option 2)

Another option is to just change the JSON::Any to String and let the user do whatever they want. This doesn't feel as slick to me but is easier. That is what I changed in this pull request.

If you get the chance please let me know your thoughts on either approach (or any others).

dyslexic-degenerate avatar Jun 04 '21 23:06 dyslexic-degenerate