4

I have been trying to get my first lambda function in Go running via the Amazon API Gateway.

I have the following package set up in go. The goal is to send a JSON request and log and return the body of that request:

package main

import (
    "net/http"
    "log"
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-lambda-go/events"
)

func Handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {

    //These log statements return empty regardless of JSON input.
    log.Print(request.body)

    return events.APIGatewayProxyResponse{
        StatusCode: http.StatusOK,
        Body: request.Body
    }, nil
}

func main() {
    lambda.Start(Handler)
}

I can build and zip this and upload it to the AWS lambda manager. The AWS lambda manager contains an option to use a test event which I can configure with a JSON string

{
  "testint": 1,
  "teststring": "test"
}

However, if I run this test, I get the following result:

{
  "statusCode": 200,
  "headers": null,
  "body": ""
}

I would expect the body to actually contain the json I passed to the function, but clearly something is going wrong.

matti0006
  • 65
  • 4
  • First, in your logging you have a typo: `log.Print(request.body)` should be `log.Print(request.Body)` – Derek Pollard Jun 12 '18 at 07:58
  • Secondly, doesn't `lamda.Start` send the context first? – Derek Pollard Jun 12 '18 at 08:00
  • For example, your handler should be: `Handler(ctx context.Context, request events.APIGatewayProxyRequest)` – Derek Pollard Jun 12 '18 at 08:01
  • @Derek adding the context doesn't seem to make a difference. It still returns an empty body (even capitalized correctly). The Amazon example also doesn't list the context: https://aws.amazon.com/blogs/compute/announcing-go-support-for-aws-lambda/ – matti0006 Jun 12 '18 at 09:30
  • In fact, the example on that website does not even work for me...it will return the error "no name was provided in the HTTP body" – matti0006 Jun 12 '18 at 09:37
  • I feel your pain... basically this tests are testing `encoding/json` Marshal/Unmarshal instead of properly testing the API Gateway functionality https://github.com/aws/aws-lambda-go/blob/master/events/apigw_test.go#L48. – Francesco Gualazzi Jun 19 '18 at 07:32
  • Chances are the body of the request is available only if you perform a POST, and not a GET. What HTTP verb are you using in your tests? Also see this other answer for Python https://stackoverflow.com/questions/46672812/aws-api-gateway-malformed-lambda-response?rq=1 – Francesco Gualazzi Jun 19 '18 at 07:40

1 Answers1

3

There's a few minor things I changed and then it works

First, log.Print(request.body) doesn't compile for me, but using request.Body is fine

Second, the type you are using for the request is

// APIGatewayProxyRequest contains data coming from the API Gateway proxy
type APIGatewayProxyRequest struct {
    Resource              string                        `json:"resource"` // The resource path defined in API Gateway
    Path                  string                        `json:"path"`     // The url path for the caller
    HTTPMethod            string                        `json:"httpMethod"`
    Headers               map[string]string             `json:"headers"`
    QueryStringParameters map[string]string             `json:"queryStringParameters"`
    PathParameters        map[string]string             `json:"pathParameters"`
    StageVariables        map[string]string             `json:"stageVariables"`
    RequestContext        APIGatewayProxyRequestContext `json:"requestContext"`
    Body                  string                        `json:"body"`
    IsBase64Encoded       bool                          `json:"isBase64Encoded,omitempty"`
}

and in this Body is a field "body" that's a string. So altering your test data to

{
  "body": "HELLO"

}

will give some data that passes through

Lastly, the parameters for the Handler in all the examples seems to include a context object, so I added that

func Handler(ctx context.Context, request events.APIGatewayProxyRequest) 

Here is a complete version of your program that "worked for me"

package main

import (
    "context"
    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
    "log"
    "net/http"
)

func Handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {

    //These log statements return empty regardless of JSON input.
    log.Print(request.Body)

    return events.APIGatewayProxyResponse{
        StatusCode: http.StatusOK,
        Body:       request.Body}, nil
}

func main() {
    lambda.Start(Handler)
}
Vorsprung
  • 32,923
  • 5
  • 39
  • 63