awslabs / aws-lambda-go-api-proxy

lambda-go-api-proxy makes it easy to port APIs written with Go frameworks such as Gin (https://gin-gonic.github.io/gin/ ) to AWS Lambda and Amazon API Gateway.
Apache License 2.0
1.08k stars 199 forks source link

Endpoint not found using Gin #142

Open garrettlove8 opened 2 years ago

garrettlove8 commented 2 years ago

Followed the instructions to a T and using this code (from the example):

var ginLambda *ginadapter.GinLambda

func init() {
    // stdout and stderr are sent to AWS CloudWatch Logs
    log.Printf("Gin cold start")
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        fmt.Println("ping route")
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })

    ginLambda = ginadapter.New(r)
}

func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    // If no name is provided in the HTTP request body, throw an error
    return ginLambda.ProxyWithContext(ctx, req)
}

func main() {
    fmt.Println("Starting Lambda request")
    lambda.Start(Handler)
}

However, getting a 404 returned when I hit this route:

{
  "message": "Not Found"
}
ashleycheung commented 2 years ago

It worked for me when I used version 2 instead of the default one

var ginLambda *ginadapter.GinLambdaV2

func init() {
    // stdout and stderr are sent to AWS CloudWatch Logs
    log.Printf("Gin cold start")
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })

    ginLambda = ginadapter.NewV2(r)
}

func Handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) {
    // If no name is provided in the HTTP request body, throw an error
    return ginLambda.ProxyWithContext(ctx, req)
}

func main() {
    lambda.Start(Handler)
}
lucianthorr commented 2 years ago

I think I'm in a similar boat, trying to get a gin-gonic to work in Lambda. @ashleycheung, using your snippet, I get a 200, "Healthy Connection" response but I don't actually get the "pong" message response. Do you? If so, would you mind sharing how your API Gateway is configured? I can get the httpadapter to work but I'm having no luck with Gin for some reason. Thanks

tschaffter commented 2 years ago

@lucianthorr The /ping path is reserved by the AWS API Gateway (see API Gateway known issues).

Example:

$ curl -i -X GET https://xxx.execute-api.us-east-1.amazonaws.com/ping
HTTP/2 200 
date: Sat, 22 Oct 2022 22:40:45 GMT
content-length: 18

Healthy Connection
$ curl -i -X GET https://xxx.execute-api.us-east-1.amazonaws.com/ping2
HTTP/2 200 
date: Sat, 22 Oct 2022 22:51:00 GMT
content-type: application/json; charset=utf-8
content-length: 13
x-powered-by: Express
etag: W/"d-NMovXDE1NuzTr1lpmBE8ZRjliFM"
apigw-requestid: abcI6gsZIAMESMA=

{"pong":true}
noce2 commented 1 year ago

@lucianthorr were you able to get an answer? @ashleycheung wouod you be able to share how yours is configured? Getting the same issue too.

noce2 commented 1 year ago

Found the issue on this, it's the payload version. It turns out if it's not specified when creating an ApiGatewayV2 integration in [Terraform] (https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/apigatewayv2_integration#payload_format_version) the payload version is assumed to be 1.0. This is possibly also the behaviour in Cloudformation. The GinLambdaV2 was expecting and v2 payload but failed on received the default set v1 payload. Hope this helps someone else.

lucianthorr commented 1 year ago

@noce2 That's great. Although it's too long ago for me to recall 100%, I believe I ended up moving over to AWS App Runner because a lot of the Api Gateway stuff is setup automatically as part of the service and from there, you don't need GinLambda to run a gin server.

foliveiracamara commented 1 year ago

@ashleycheung This worked as well for me using echoadapter.EchoLambdaV2, thanks for your answer, been struggling for 2 days.

dsncode commented 4 months ago

a small snippet that worked for me by using echoadapter.EchoLambdaV2. I hope it helps someone else as well

package main

import (
    "context"
    "net/http"
    "time"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
    echoadapter "github.com/awslabs/aws-lambda-go-api-proxy/echo"
    "github.com/labstack/echo/v4"
)

type Response struct {
    From    string
    Message string
}

var echoLambda *echoadapter.EchoLambdaV2

func init() {
    e := echo.New()
    e.GET("/", func(c echo.Context) error {
        return c.JSON(http.StatusOK, Response{From: "/", Message: time.Now().Format(time.UnixDate)})
    })

    e.GET("/ping", func(c echo.Context) error {
        return c.JSON(http.StatusOK, Response{From: "/ping", Message: time.Now().Format(time.UnixDate)})
    })

    echoLambda = echoadapter.NewV2(e)
}

func Handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) (events.APIGatewayV2HTTPResponse, error) {
    return echoLambda.ProxyWithContext(ctx, req)
}

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