Search code examples
amazon-web-servicesgoaws-lambdaamazon-sqs

aws lambda in golang triggered by sqs and getting type errors


I'm developing a lambda that is triggered by API Gateway and SQS.

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"

    regcode "company/gateway/lambda/regcode/lib"
)

func main() {

    // Start the Lambda function with both SQS and Lambda URL handlers
    lambda.Start(func(ctx context.Context, event interface{}) error {
        fmt.Println("Event type: ", event)
        switch event.(type) {
        case events.SQSEvent:
            return regcode.HandlerSqs(ctx, event.(events.SQSEvent))
        case events.APIGatewayProxyRequest:
            response, err := regcode.HandlerLambdaURL(ctx, event.(events.APIGatewayProxyRequest))
            if err != nil {
                log.Println(err)
                return err
            }
            log.Printf("API Gateway response: %v", response)
            return nil
        default:
            return fmt.Errorf("unknown event type: %T", event)
        }
    })
}

But my switch type is not able to identify when I use an sqs or apigateway event. It always falls in the default statement. For SQS for instance I'm using this event:

{
  "Records": [
    {
      "messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78",
      "receiptHandle": "MessageReceiptHandle",
      "body": "Hello from SQS!",
      "attributes": {
        "ApproximateReceiveCount": "1",
        "SentTimestamp": "1523232000000",
        "SenderId": "123456789012",
        "ApproximateFirstReceiveTimestamp": "1523232000001"
      },
      "messageAttributes": {},
      "md5OfBody": "{{{md5_of_body}}}",
      "md5OfMessageAttributes": "test",
      "eventSource": "aws:sqs",
      "eventSourceARN": "arn:aws:sqs:us-east-1:123456789012:MyQueue",
      "awsRegion": "us-east-1"
    }
  ]
}

and getting this message:

unknown event type: map[string]interface {}: errorString

Any idea what I'm doing wrong? I'm new to using golang so I'm lost here.

Also, I tried to send the event directly to the regcode.HandlerSqs, but I got a type conversion error. Like this:

func main() {

    // Start the Lambda function with both SQS and Lambda URL handlers
    lambda.Start(func(ctx context.Context, event interface{}) error {
        sqsEvent, _ := event.(SQSEvent)
        // ...
    })
}

sqsEvent is empty.


Solution

  • Any idea what I'm doing wrong?

    AWS lambda handler will reflect types of your arguments in func, and then will create event type matching your signature.

    So if you declare your func to be have second argument as event events.SQSEvent, AWS will get its type, events.SQSEvent, creates such an object, and pass it in.

    Same, if you are going to use event events.APIGatewayProxyRequest in func, aws will reflect that event should be events.APIGatewayProxyRequest and will create that.

    In other words, AWS does not check whether the incoming request is from SQS or API. This is only determined based on your handler's signature. So if you use event interface{} in func, aws creates exactly what you specified to be created, interface{}, not any other type.

    So that's why your switch does not work. The easiest way to fix that, would be to have two lambda functions, with for SQS and one for API.