diff --git a/README.md b/README.md index 33437cd..4c4de9a 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ $ go get github.com/aws/aws-lambda-go/lambda $ go get github.com/awslabs/aws-lambda-go-api-proxy/... ``` -Following the instructions from the [Lambda documentation](https://docs.aws.amazon.com/lambda/latest/dg/go-programming-model-handler-types.html), we need to declare a `Handler` method for our main package. We will declare a `ginadapter.GinLambda` object -in the global scope, initialized once it in the Handler with all its API methods, and then use the `Proxy` method to translate requests and responses +Following the instructions from the [Lambda documentation](https://docs.aws.amazon.com/lambda/latest/dg/go-programming-model-handler-types.html), we need to declare a `Handler` method for our main package. +We will declare a `httpadapter.HandlerAdapter` object in the global scope, initialized once it in the Handler with all its API methods, and then use the `Proxy` method to translate requests and responses ```go package main @@ -25,11 +25,11 @@ import ( "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" - "github.com/awslabs/aws-lambda-go-api-proxy/gin" + "github.com/awslabs/aws-lambda-go-api-proxy/httpadapter" "github.com/gin-gonic/gin" ) -var ginLambda *ginadapter.GinLambda +var ginLambda *httpadapter.HandlerAdapter func init() { // stdout and stderr are sent to AWS CloudWatch Logs @@ -41,7 +41,7 @@ func init() { }) }) - ginLambda = ginadapter.New(r) + ginLambda = httpadapter.New(r) } func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { @@ -78,10 +78,10 @@ $ aws cloudformation deploy --template-file output-sam.yaml --stack-name YOUR_ST Using the CloudFormation console, you can find the URL for the newly created API endpoint in the `Outputs` tab of the sample stack - it looks sample like this: `https://xxxxxxxxx.execute-api.xx-xxxx-x.amazonaws.com/Prod/pets`. Open a browser window and try to call the URL. ## API Gateway context and stage variables -The `RequestAccessor` object, and therefore `GinLambda`, automatically marshals the API Gateway request context and stage variables objects and stores them in custom headers in the request: `X-GinLambda-ApiGw-Context` and `X-GinLambda-ApiGw-StageVars`. While you could manually unmarshal the json content into the `events.APIGatewayProxyRequestContext` and `map[string]string` objects, the library exports two utility methods to give you easy access to the data. +The `RequestAccessor` object, and therefore `HandlerAdapter`, automatically marshals the API Gateway request context and stage variables objects and stores them in custom headers in the request: `X-GinLambda-ApiGw-Context` and `X-GinLambda-ApiGw-StageVars`. While you could manually unmarshal the json content into the `events.APIGatewayProxyRequestContext` and `map[string]string` objects, the library exports two utility methods to give you easy access to the data. ```go -// the methods are available in your instance of the GinLambda +// the methods are available in your instance of the HandlerAdapter // object and receive the http.Request object apiGwContext := ginLambda.GetAPIGatewayContext(c.Request) apiGwStageVars := ginLambda.GetAPIGatewayStageVars(c.Request) @@ -97,11 +97,11 @@ stageVarValue := apiGwStageVars["MyStageVar"] ## Supporting other frameworks The `aws-lambda-go-api-proxy`, alongside the various adapters, declares a `core` package. The `core` package, contains utility methods and interfaces to translate API Gateway proxy events into Go's default `http.Request` and `http.ResponseWriter` objects. -You can see that the [`ginlambda.go`](gin/adapter.go) file extends the `RequestAccessor` struct defined in the [`request.go`](core/request.go) file. `RequestAccessor` gives you access to the `ProxyEventToHTTPRequest()` method. +You can see that the [`adapter.go`](httpadapter/adapter.go) file extends the `RequestAccessor` struct defined in the [`request.go`](core/request.go) file. `RequestAccessor` gives you access to the `ProxyEventToHTTPRequest()` method. -The `GinLambda` object is initialized with an instance of `gin.Engine`. `gin.Engine` implements methods defined in the `http.Handler` interface. +The `HandlerAdapter` object is initialized with an instance of `gin.Engine`. `gin.Engine` implements methods defined in the `http.Handler` interface. -The `Proxy` method of the `GinLambda` object simply receives the `events.APIGatewayProxyRequest` object and uses the `ProxyEventToHTTPRequest()` method to convert it into an `http.Request` object. Next, it creates a new `ProxyResponseWriter` object (defined in the [`response.go`](core/response.go)) file and passes both request and response writer to the `ServeHTTP` method of the `gin.Engine`. +The `Proxy` method of the `HandlerAdapter` object simply receives the `events.APIGatewayProxyRequest` object and uses the `ProxyEventToHTTPRequest()` method to convert it into an `http.Request` object. Next, it creates a new `ProxyResponseWriter` object (defined in the [`response.go`](core/response.go)) file and passes both request and response writer to the `ServeHTTP` method of the `gin.Engine`. The `ProxyResponseWriter` exports a method called `GetProxyResponse()` to generate an `events.APIGatewayProxyResponse` object from the data written to the response writer. diff --git a/chi/adapter.go b/chi/adapter.go deleted file mode 100644 index f578a1c..0000000 --- a/chi/adapter.go +++ /dev/null @@ -1,62 +0,0 @@ -// Packge chilambda add Chi support for the aws-severless-go-api library. -// Uses the core package behind the scenes and exposes the New method to -// get a new instance and Proxy method to send request to the Chi mux. -package chiadapter - -import ( - "context" - "net/http" - - "github.com/aws/aws-lambda-go/events" - "github.com/awslabs/aws-lambda-go-api-proxy/core" - "github.com/go-chi/chi" -) - -// ChiLambda makes it easy to send API Gateway proxy events to a Chi -// Mux. The library transforms the proxy event into an HTTP request and then -// creates a proxy response object from the http.ResponseWriter -type ChiLambda struct { - core.RequestAccessor - - chiMux *chi.Mux -} - -// New creates a new instance of the ChiLambda object. -// Receives an initialized *chi.Mux object - normally created with chi.NewRouter(). -// It returns the initialized instance of the ChiLambda object. -func New(chi *chi.Mux) *ChiLambda { - return &ChiLambda{chiMux: chi} -} - -// Proxy receives an API Gateway proxy event, transforms it into an http.Request -// object, and sends it to the chi.Mux for routing. -// It returns a proxy response object generated from the http.ResponseWriter. -func (g *ChiLambda) Proxy(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - chiRequest, err := g.ProxyEventToHTTPRequest(req) - return g.proxyInternal(chiRequest, err) -} - -// ProxyWithContext receives context and an API Gateway proxy event, -// transforms them into an http.Request object, and sends it to the chi.Mux for routing. -// It returns a proxy response object generated from the http.ResponseWriter. -func (g *ChiLambda) ProxyWithContext(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - chiRequest, err := g.EventToRequestWithContext(ctx, req) - return g.proxyInternal(chiRequest, err) -} - -func (g *ChiLambda) proxyInternal(chiRequest *http.Request, err error) (events.APIGatewayProxyResponse, error) { - - if err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Could not convert proxy event to request: %v", err) - } - - respWriter := core.NewProxyResponseWriter() - g.chiMux.ServeHTTP(http.ResponseWriter(respWriter), chiRequest) - - proxyResponse, err := respWriter.GetProxyResponse() - if err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Error while generating proxy response: %v", err) - } - - return proxyResponse, nil -} diff --git a/chi/chi_suite_test.go b/chi/chi_suite_test.go deleted file mode 100644 index 387fab5..0000000 --- a/chi/chi_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package chiadapter_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestChi(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Chi Suite") -} diff --git a/chi/chilambda_test.go b/chi/chilambda_test.go deleted file mode 100644 index 7e6fba4..0000000 --- a/chi/chilambda_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package chiadapter_test - -import ( - "context" - "log" - "net/http" - - "github.com/aws/aws-lambda-go/events" - chiadapter "github.com/awslabs/aws-lambda-go-api-proxy/chi" - "github.com/go-chi/chi" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("ChiLambda tests", func() { - Context("Simple ping request", func() { - It("Proxies the event correctly", func() { - log.Println("Starting test") - - r := chi.NewRouter() - r.Get("/ping", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("pong")) - }) - - adapter := chiadapter.New(r) - - req := events.APIGatewayProxyRequest{ - Path: "/ping", - HTTPMethod: "GET", - } - - resp, err := adapter.ProxyWithContext(context.Background(), req) - - Expect(err).To(BeNil()) - Expect(resp.StatusCode).To(Equal(200)) - - resp, err = adapter.Proxy(req) - Expect(err).To(BeNil()) - Expect(resp.StatusCode).To(Equal(200)) - }) - }) -}) diff --git a/echo/adapter.go b/echo/adapter.go deleted file mode 100644 index 0ddd9cf..0000000 --- a/echo/adapter.go +++ /dev/null @@ -1,62 +0,0 @@ -// Packge echolambda add Echo support for the aws-severless-go-api library. -// Uses the core package behind the scenes and exposes the New method to -// get a new instance and Proxy method to send request to the echo.Echo -package echoadapter - -import ( - "context" - "net/http" - - "github.com/aws/aws-lambda-go/events" - "github.com/awslabs/aws-lambda-go-api-proxy/core" - "github.com/labstack/echo/v4" -) - -// EchoLambda makes it easy to send API Gateway proxy events to a echo.Echo. -// The library transforms the proxy event into an HTTP request and then -// creates a proxy response object from the http.ResponseWriter -type EchoLambda struct { - core.RequestAccessor - - Echo *echo.Echo -} - -// New creates a new instance of the EchoLambda object. -// Receives an initialized *echo.Echo object - normally created with echo.New(). -// It returns the initialized instance of the EchoLambda object. -func New(e *echo.Echo) *EchoLambda { - return &EchoLambda{Echo: e} -} - -// Proxy receives an API Gateway proxy event, transforms it into an http.Request -// object, and sends it to the echo.Echo for routing. -// It returns a proxy response object generated from the http.ResponseWriter. -func (e *EchoLambda) Proxy(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - echoRequest, err := e.ProxyEventToHTTPRequest(req) - return e.proxyInternal(echoRequest, err) -} - -// ProxyWithContext receives context and an API Gateway proxy event, -// transforms them into an http.Request object, and sends it to the echo.Echo for routing. -// It returns a proxy response object generated from the http.ResponseWriter. -func (e *EchoLambda) ProxyWithContext(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - echoRequest, err := e.EventToRequestWithContext(ctx, req) - return e.proxyInternal(echoRequest, err) -} - -func (e *EchoLambda) proxyInternal(req *http.Request, err error) (events.APIGatewayProxyResponse, error) { - - if err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Could not convert proxy event to request: %v", err) - } - - respWriter := core.NewProxyResponseWriter() - e.Echo.ServeHTTP(http.ResponseWriter(respWriter), req) - - proxyResponse, err := respWriter.GetProxyResponse() - if err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Error while generating proxy response: %v", err) - } - - return proxyResponse, nil -} diff --git a/echo/echo_suite_test.go b/echo/echo_suite_test.go deleted file mode 100644 index 76efb74..0000000 --- a/echo/echo_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package echoadapter_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestEcho(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Echo Suite") -} diff --git a/echo/echolambda_test.go b/echo/echolambda_test.go deleted file mode 100644 index 68cc7a6..0000000 --- a/echo/echolambda_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package echoadapter_test - -import ( - "log" - - "github.com/aws/aws-lambda-go/events" - echoadapter "github.com/awslabs/aws-lambda-go-api-proxy/echo" - "github.com/labstack/echo/v4" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("EchoLambda tests", func() { - Context("Simple ping request", func() { - It("Proxies the event correctly", func() { - log.Println("Starting test") - e := echo.New() - e.GET("/ping", func(c echo.Context) error { - log.Println("Handler!!") - return c.String(200, "pong") - }) - - adapter := echoadapter.New(e) - - req := events.APIGatewayProxyRequest{ - Path: "/ping", - HTTPMethod: "GET", - } - - resp, err := adapter.Proxy(req) - - Expect(err).To(BeNil()) - Expect(resp.StatusCode).To(Equal(200)) - }) - }) -}) diff --git a/gin/adapter.go b/gin/adapter.go deleted file mode 100644 index c313e64..0000000 --- a/gin/adapter.go +++ /dev/null @@ -1,62 +0,0 @@ -// Package ginadapter adds Gin support for the aws-severless-go-api library. -// Uses the core package behind the scenes and exposes the New method to -// get a new instance and Proxy method to send request to the Gin engine. -package ginadapter - -import ( - "context" - "net/http" - - "github.com/aws/aws-lambda-go/events" - "github.com/awslabs/aws-lambda-go-api-proxy/core" - "github.com/gin-gonic/gin" -) - -// GinLambda makes it easy to send API Gateway proxy events to a Gin -// Engine. The library transforms the proxy event into an HTTP request and then -// creates a proxy response object from the http.ResponseWriter -type GinLambda struct { - core.RequestAccessor - - ginEngine *gin.Engine -} - -// New creates a new instance of the GinLambda object. -// Receives an initialized *gin.Engine object - normally created with gin.Default(). -// It returns the initialized instance of the GinLambda object. -func New(gin *gin.Engine) *GinLambda { - return &GinLambda{ginEngine: gin} -} - -// Proxy receives an API Gateway proxy event, transforms it into an http.Request -// object, and sends it to the gin.Engine for routing. -// It returns a proxy response object generated from the http.ResponseWriter. -func (g *GinLambda) Proxy(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - ginRequest, err := g.ProxyEventToHTTPRequest(req) - return g.proxyInternal(ginRequest, err) -} - -// ProxyWithContext receives context and an API Gateway proxy event, -// transforms them into an http.Request object, and sends it to the gin.Engine for routing. -// It returns a proxy response object generated from the http.ResponseWriter. -func (g *GinLambda) ProxyWithContext(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - ginRequest, err := g.EventToRequestWithContext(ctx, req) - return g.proxyInternal(ginRequest, err) -} - -func (g *GinLambda) proxyInternal(req *http.Request, err error) (events.APIGatewayProxyResponse, error) { - - if err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Could not convert proxy event to request: %v", err) - } - - respWriter := core.NewProxyResponseWriter() - g.ginEngine.ServeHTTP(http.ResponseWriter(respWriter), req) - - proxyResponse, err := respWriter.GetProxyResponse() - if err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Error while generating proxy response: %v", err) - } - - return proxyResponse, nil -} diff --git a/gin/gin_suite_test.go b/gin/gin_suite_test.go deleted file mode 100644 index 21222f8..0000000 --- a/gin/gin_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package ginadapter_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestGin(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Gin Suite") -} diff --git a/gin/ginlambda_test.go b/gin/ginlambda_test.go deleted file mode 100644 index db90c76..0000000 --- a/gin/ginlambda_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package ginadapter_test - -import ( - "context" - "log" - - "github.com/aws/aws-lambda-go/events" - ginadapter "github.com/awslabs/aws-lambda-go-api-proxy/gin" - "github.com/gin-gonic/gin" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("GinLambda tests", func() { - Context("Simple ping request", func() { - It("Proxies the event correctly", func() { - log.Println("Starting test") - r := gin.Default() - r.GET("/ping", func(c *gin.Context) { - log.Println("Handler!!") - c.JSON(200, gin.H{ - "message": "pong", - }) - }) - - adapter := ginadapter.New(r) - - req := events.APIGatewayProxyRequest{ - Path: "/ping", - HTTPMethod: "GET", - } - - resp, err := adapter.ProxyWithContext(context.Background(), req) - - Expect(err).To(BeNil()) - Expect(resp.StatusCode).To(Equal(200)) - - resp, err = adapter.Proxy(req) - - Expect(err).To(BeNil()) - Expect(resp.StatusCode).To(Equal(200)) - }) - }) -}) diff --git a/go.mod b/go.mod index 22babf6..8214aa4 100644 --- a/go.mod +++ b/go.mod @@ -36,6 +36,7 @@ require ( github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect github.com/yudai/pp v2.0.1+incompatible // indirect + goji.io v2.0.2+incompatible golang.org/x/sys v0.0.0-20201016160150-f659759dc4ca // indirect google.golang.org/protobuf v1.25.0 // indirect ) diff --git a/go.sum b/go.sum index f554f94..ffd2ee6 100644 --- a/go.sum +++ b/go.sum @@ -265,6 +265,8 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3Ifn github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +goji.io v2.0.2+incompatible h1:uIssv/elbKRLznFUy3Xj4+2Mz/qKhek/9aZQDUMae7c= +goji.io v2.0.2+incompatible/go.mod h1:sbqFwrtqZACxLBTQcdgVjFh54yGVCvwq8+w49MVMMIk= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -362,6 +364,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.51.1 h1:GyboHr4UqMiLUybYjd22ZjQIKEJEpgtLXtuGbR21Oho= gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= diff --git a/gorillamux/adapter.go b/gorillamux/adapter.go deleted file mode 100644 index 33baf6a..0000000 --- a/gorillamux/adapter.go +++ /dev/null @@ -1,53 +0,0 @@ -package gorillamux - -import ( - "context" - "net/http" - - "github.com/aws/aws-lambda-go/events" - "github.com/awslabs/aws-lambda-go-api-proxy/core" - "github.com/gorilla/mux" -) - -type GorillaMuxAdapter struct { - core.RequestAccessor - router *mux.Router -} - -func New(router *mux.Router) *GorillaMuxAdapter { - return &GorillaMuxAdapter{ - router: router, - } -} - -// Proxy receives an API Gateway proxy event, transforms it into an http.Request -// object, and sends it to the mux.Router for routing. -// It returns a proxy response object generated from the http.ResponseWriter. -func (h *GorillaMuxAdapter) Proxy(event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - req, err := h.ProxyEventToHTTPRequest(event) - return h.proxyInternal(req, err) -} - -// ProxyWithContext receives context and an API Gateway proxy event, -// transforms them into an http.Request object, and sends it to the mux.Router for routing. -// It returns a proxy response object generated from the http.ResponseWriter. -func (h *GorillaMuxAdapter) ProxyWithContext(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - req, err := h.EventToRequestWithContext(ctx, event) - return h.proxyInternal(req, err) -} - -func (h *GorillaMuxAdapter) proxyInternal(req *http.Request, err error) (events.APIGatewayProxyResponse, error) { - if err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Could not convert proxy event to request: %v", err) - } - - w := core.NewProxyResponseWriter() - h.router.ServeHTTP(http.ResponseWriter(w), req) - - resp, err := w.GetProxyResponse() - if err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Error while generating proxy response: %v", err) - } - - return resp, nil -} diff --git a/gorillamux/adapter_test.go b/gorillamux/adapter_test.go deleted file mode 100644 index fbc9a63..0000000 --- a/gorillamux/adapter_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package gorillamux_test - -import ( - "context" - "fmt" - "net/http" - - "github.com/aws/aws-lambda-go/events" - "github.com/awslabs/aws-lambda-go-api-proxy/gorillamux" - "github.com/gorilla/mux" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("GorillaMuxAdapter tests", func() { - Context("Simple ping request", func() { - It("Proxies the event correctly", func() { - homeHandler := func(w http.ResponseWriter, req *http.Request) { - w.Header().Add("unfortunately-required-header", "") - fmt.Fprintf(w, "Home Page") - } - - productsHandler := func(w http.ResponseWriter, req *http.Request) { - w.Header().Add("unfortunately-required-header", "") - fmt.Fprintf(w, "Products Page") - } - - r := mux.NewRouter() - r.HandleFunc("/", homeHandler) - r.HandleFunc("/products", productsHandler) - - adapter := gorillamux.New(r) - - homePageReq := events.APIGatewayProxyRequest{ - Path: "/", - HTTPMethod: "GET", - } - - homePageResp, homePageReqErr := adapter.ProxyWithContext(context.Background(), homePageReq) - - Expect(homePageReqErr).To(BeNil()) - Expect(homePageResp.StatusCode).To(Equal(200)) - Expect(homePageResp.Body).To(Equal("Home Page")) - - productsPageReq := events.APIGatewayProxyRequest{ - Path: "/products", - HTTPMethod: "GET", - } - - productsPageResp, productsPageReqErr := adapter.Proxy(productsPageReq) - - Expect(productsPageReqErr).To(BeNil()) - Expect(productsPageResp.StatusCode).To(Equal(200)) - Expect(productsPageResp.Body).To(Equal("Products Page")) - }) - }) -}) diff --git a/gorillamux/gorilla_suite_test.go b/gorillamux/gorilla_suite_test.go deleted file mode 100644 index 8b996a3..0000000 --- a/gorillamux/gorilla_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package gorillamux_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestGorillaMux(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Gorilla Mux Suite") -} diff --git a/httpadapter/libraries_test.go b/httpadapter/libraries_test.go new file mode 100644 index 0000000..579ad91 --- /dev/null +++ b/httpadapter/libraries_test.go @@ -0,0 +1,138 @@ +package httpadapter_test + +import ( + "context" + "fmt" + "log" + "net/http" + + "github.com/aws/aws-lambda-go/events" + "github.com/awslabs/aws-lambda-go-api-proxy/httpadapter" + "github.com/gin-gonic/gin" + "github.com/go-chi/chi" + "github.com/gorilla/mux" + "github.com/kataras/iris/v12" + "github.com/labstack/echo/v4" + "github.com/urfave/negroni" + "goji.io" + "goji.io/pat" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("HTTPAdapter tests", func() { + Context("Simple ping request", func() { + tests := []struct { + name string + handler http.Handler + }{ + { + name: "chi", + handler: func() http.Handler { + r := chi.NewRouter() + r.Get("/ping", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "pong") + }) + + return r + }(), + }, + { + name: "echo", + handler: func() http.Handler { + e := echo.New() + e.GET("/ping", func(c echo.Context) error { + return c.String(200, "pong") + }) + + return e + }(), + }, + { + name: "gin", + handler: func() http.Handler { + gin.SetMode(gin.ReleaseMode) + + r := gin.New() + r.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + + return r + }(), + }, + { + name: "goji", + handler: func() http.Handler { + r := goji.NewMux() + r.HandleFunc(pat.Get("/ping"), func(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "pong") + }) + + return r + }(), + }, + { + name: "gorillamux", + handler: func() http.Handler { + r := mux.NewRouter() + r.HandleFunc("/ping", func(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "pong") + }) + + return r + }(), + }, + { + name: "iris", + handler: func() http.Handler { + app := iris.Default() + app.Get("/ping", func(ctx iris.Context) { + log.Println("Handler!!") + ctx.WriteString("pong") + }) + app.Build() + + return app + }(), + }, + { + name: "negroni", + handler: func() http.Handler { + mux := http.NewServeMux() + mux.HandleFunc("/ping", func(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "pong") + }) + + n := negroni.New() + n.UseHandler(mux) + + return n + }(), + }, + } + + req := events.APIGatewayProxyRequest{ + Path: "/ping", + HTTPMethod: "GET", + } + + for i := range tests { + test := tests[i] + It("Proxies the event to "+test.name, func() { + adapter := httpadapter.New(test.handler) + + resp, err := adapter.ProxyWithContext(context.Background(), req) + Expect(err).To(BeNil()) + Expect(resp.StatusCode).To(Equal(200)) + Expect(resp.Body).To(Equal("pong")) + + resp, err = adapter.Proxy(req) + Expect(err).To(BeNil()) + Expect(resp.StatusCode).To(Equal(200)) + Expect(resp.Body).To(Equal("pong")) + }) + } + }) +}) diff --git a/iris/adapter.go b/iris/adapter.go deleted file mode 100644 index d36ae28..0000000 --- a/iris/adapter.go +++ /dev/null @@ -1,65 +0,0 @@ -// Package irisLambda add Iris support for the aws-serverless-go-api library. -// Uses the core package behind the scenes and exposes the New method to -// get a new instance and Proxy method to send request to the iris.Application. -package irisadapter - -import ( - "context" - "net/http" - - "github.com/aws/aws-lambda-go/events" - "github.com/awslabs/aws-lambda-go-api-proxy/core" - "github.com/kataras/iris/v12" -) - -// IrisLambda makes it easy to send API Gateway proxy events to a iris.Application. -// The library transforms the proxy event into an HTTP request and then -// creates a proxy response object from the http.ResponseWriter -type IrisLambda struct { - core.RequestAccessor - - application *iris.Application -} - -// New creates a new instance of the IrisLambda object. -// Receives an initialized *iris.Application object - normally created with iris.Default(). -// It returns the initialized instance of the IrisLambda object. -func New(app *iris.Application) *IrisLambda { - return &IrisLambda{application: app} -} - -// Proxy receives an API Gateway proxy event, transforms it into an http.Request -// object, and sends it to the iris.Application for routing. -// It returns a proxy response object generated from the http.ResponseWriter. -func (i *IrisLambda) Proxy(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - irisRequest, err := i.ProxyEventToHTTPRequest(req) - return i.proxyInternal(irisRequest, err) -} - -// ProxyWithContext receives context and an API Gateway proxy event, -// transforms them into an http.Request object, and sends it to the iris.Application for routing. -// It returns a proxy response object generated from the http.ResponseWriter. -func (i *IrisLambda) ProxyWithContext(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - irisRequest, err := i.EventToRequestWithContext(ctx, req) - return i.proxyInternal(irisRequest, err) -} - -func (i *IrisLambda) proxyInternal(req *http.Request, err error) (events.APIGatewayProxyResponse, error) { - if err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Could not convert proxy event to request: %v", err) - } - - if err := i.application.Build(); err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Iris set up failed: %v", err) - } - - respWriter := core.NewProxyResponseWriter() - i.application.ServeHTTP(http.ResponseWriter(respWriter), req) - - proxyResponse, err := respWriter.GetProxyResponse() - if err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Error while generating proxy response: %v", err) - } - - return proxyResponse, nil -} diff --git a/iris/iris_suite_test.go b/iris/iris_suite_test.go deleted file mode 100644 index eceb6f1..0000000 --- a/iris/iris_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package irisadapter_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestEcho(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Iris Suite") -} diff --git a/iris/irislambda_test.go b/iris/irislambda_test.go deleted file mode 100644 index 79e1e1f..0000000 --- a/iris/irislambda_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package irisadapter_test - -import ( - "context" - "log" - - "github.com/aws/aws-lambda-go/events" - irisadapter "github.com/awslabs/aws-lambda-go-api-proxy/iris" - "github.com/kataras/iris/v12" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("IrisLambda tests", func() { - Context("Simple ping request", func() { - It("Proxies the event correctly", func() { - log.Println("Starting test") - - app := iris.New() - app.Get("/ping", func(ctx iris.Context) { - log.Println("Handler!!") - ctx.WriteString("pong") - }) - - adapter := irisadapter.New(app) - - req := events.APIGatewayProxyRequest{ - Path: "/ping", - HTTPMethod: "GET", - } - - resp, err := adapter.ProxyWithContext(context.Background(), req) - - Expect(err).To(BeNil()) - Expect(resp.StatusCode).To(Equal(200)) - - resp, err = adapter.Proxy(req) - - Expect(err).To(BeNil()) - Expect(resp.StatusCode).To(Equal(200)) - }) - }) -}) diff --git a/negroni/adapter.go b/negroni/adapter.go deleted file mode 100644 index ecafdaf..0000000 --- a/negroni/adapter.go +++ /dev/null @@ -1,53 +0,0 @@ -package negroniadapter - -import ( - "context" - "net/http" - - "github.com/aws/aws-lambda-go/events" - "github.com/awslabs/aws-lambda-go-api-proxy/core" - "github.com/urfave/negroni" -) - -type NegroniAdapter struct { - core.RequestAccessor - n *negroni.Negroni -} - -func New(n *negroni.Negroni) *NegroniAdapter { - return &NegroniAdapter{ - n: n, - } -} - -// Proxy receives an API Gateway proxy event, transforms it into an http.Request -// object, and sends it to the negroni.Negroni for routing. -// It returns a proxy response object generated from the http.Handler. -func (h *NegroniAdapter) Proxy(event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - req, err := h.ProxyEventToHTTPRequest(event) - return h.proxyInternal(req, err) -} - -// ProxyWithContext receives context and an API Gateway proxy event, -// transforms them into an http.Request object, and sends it to the negroni.Negroni for routing. -// It returns a proxy response object generated from the http.ResponseWriter. -func (h *NegroniAdapter) ProxyWithContext(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - req, err := h.EventToRequestWithContext(ctx, event) - return h.proxyInternal(req, err) -} - -func (h *NegroniAdapter) proxyInternal(req *http.Request, err error) (events.APIGatewayProxyResponse, error) { - if err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Could not convert proxy event to request: %v", err) - } - - w := core.NewProxyResponseWriter() - h.n.ServeHTTP(http.ResponseWriter(w), req) - - resp, err := w.GetProxyResponse() - if err != nil { - return core.GatewayTimeout(), core.NewLoggedError("Error while generating proxy response: %v", err) - } - - return resp, nil -} diff --git a/negroni/adapter_test.go b/negroni/adapter_test.go deleted file mode 100644 index b1a8df4..0000000 --- a/negroni/adapter_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package negroniadapter_test - -import ( - "context" - "fmt" - "log" - "net/http" - - "github.com/aws/aws-lambda-go/events" - negroniadapter "github.com/awslabs/aws-lambda-go-api-proxy/negroni" - "github.com/urfave/negroni" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("NegroniAdapter tests", func() { - Context("Tests multiple handlers", func() { - It("Proxies the event correctly", func() { - log.Println("Starting test") - - homeHandler := func(w http.ResponseWriter, req *http.Request) { - w.Header().Add("unfortunately-required-header", "") - fmt.Fprintf(w, "Home Page") - } - - productsHandler := func(w http.ResponseWriter, req *http.Request) { - w.Header().Add("unfortunately-required-header", "") - fmt.Fprintf(w, "Products Page") - } - - mux := http.NewServeMux() - mux.HandleFunc("/", homeHandler) - mux.HandleFunc("/products", productsHandler) - - n := negroni.New() - n.UseHandler(mux) - - adapter := negroniadapter.New(n) - - homePageReq := events.APIGatewayProxyRequest{ - Path: "/", - HTTPMethod: "GET", - } - - homePageResp, homePageReqErr := adapter.ProxyWithContext(context.Background(), homePageReq) - - Expect(homePageReqErr).To(BeNil()) - Expect(homePageResp.StatusCode).To(Equal(200)) - Expect(homePageResp.Body).To(Equal("Home Page")) - - productsPageReq := events.APIGatewayProxyRequest{ - Path: "/products", - HTTPMethod: "GET", - } - - productsPageResp, productsPageReqErr := adapter.Proxy(productsPageReq) - - Expect(productsPageReqErr).To(BeNil()) - Expect(productsPageResp.StatusCode).To(Equal(200)) - Expect(productsPageResp.Body).To(Equal("Products Page")) - }) - }) -}) diff --git a/negroni/negroni_suite_test.go b/negroni/negroni_suite_test.go deleted file mode 100644 index 2afee57..0000000 --- a/negroni/negroni_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package negroniadapter_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestNegroni(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "NegroniAdapter Suite") -}