From 788ca1d041fbaa8e724a73289edc7890d3a0e700 Mon Sep 17 00:00:00 2001 From: John Fallis Date: Wed, 20 Sep 2023 14:54:38 +0100 Subject: [PATCH] g8 http server migration --- http.go | 48 +++++++++++++++++++++++++----------------------- http_test.go | 28 +++++++++++++++------------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/http.go b/http.go index e394343..4680bb1 100644 --- a/http.go +++ b/http.go @@ -1,25 +1,25 @@ package g8 import ( - "context" "encoding/json" "fmt" - "github.com/aws/aws-lambda-go/events" - "github.com/go-chi/chi/v5" "io" "net/http" "strings" + + "github.com/aws/aws-lambda-go/events" + "github.com/go-chi/chi/v5" ) const ( - WELCOME_MESSAGE = "G8 HTTP server is running on port" - UNHANDLED_ERR_MESSAGE = "unhandled error: " + WelcomeMessage = "G8 HTTP server is running on port" + UnhandledErrMessage = "unhandled error: " ) type LambdaHandlerEndpoints []LambdaHandler type LambdaHandler struct { - Handler interface{} + Handler any Method string Path string PathParams []string @@ -27,7 +27,7 @@ type LambdaHandler struct { // NewHTTPHandler creates a new HTTP server that listens on the given port. func NewHTTPHandler(lambdaEndpoints LambdaHandlerEndpoints, portNumber int) { - fmt.Printf("\n%s %d\n\n", WELCOME_MESSAGE, portNumber) + fmt.Printf("\n%s %d\n\n", WelcomeMessage, portNumber) r := chi.NewRouter() for _, l := range lambdaEndpoints { r.MethodFunc(l.Method, l.Path, LambdaAdapter(l)) @@ -41,28 +41,30 @@ func NewHTTPHandler(lambdaEndpoints LambdaHandlerEndpoints, portNumber int) { func LambdaAdapter(l LambdaHandler) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { switch eventHandler := l.Handler.(type) { - // APIGatewayProxyHandler - case func(context.Context, events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error): + case func(ctx *APIGatewayProxyContext) error: fmt.Printf("%s %s: %+v \n", r.Method, r.URL.Path, l.PathParams) - request := NewAPIGatewayRequestBuilder(r, l.PathParams) - resp, eErr := eventHandler(context.Background(), request.Request()) - if eErr != nil { - fmt.Printf("%s %s\n", UNHANDLED_ERR_MESSAGE, eErr.Error()) - resp, eErr = unhandledError(eErr) - if eErr != nil { - panic(eErr) + ctx := &APIGatewayProxyContext{ + Request: NewAPIGatewayRequestBuilder(r, l.PathParams).Request(), + } + + if eErr := eventHandler(ctx); eErr != nil { + fmt.Printf("%s %s\n", UnhandledErrMessage, eErr.Error()) + resp, uErr := unhandledError(eErr) + if uErr != nil { + panic(uErr) } + ctx.Response = resp } w.Header().Set("Content-Type", "application/json") - for k, v := range resp.Headers { + for k, v := range ctx.Response.Headers { w.Header().Set(k, v) } - for k, v := range resp.MultiValueHeaders { + for k, v := range ctx.Response.MultiValueHeaders { w.Header().Set(k, strings.Join(v, ",")) } - w.WriteHeader(resp.StatusCode) - if _, wErr := w.Write([]byte(resp.Body)); wErr != nil { + w.WriteHeader(ctx.Response.StatusCode) + if _, wErr := w.Write([]byte(ctx.Response.Body)); wErr != nil { panic(wErr) } default: @@ -142,7 +144,7 @@ func NewAPIGatewayRequestBuilder(request *http.Request, pathParams []string) *AP } // unhandledError returns an APIGatewayProxyResponse with the given error. -func unhandledError(err error) (*events.APIGatewayProxyResponse, error) { +func unhandledError(err error) (events.APIGatewayProxyResponse, error) { var newErr Err switch err := err.(type) { case Err: @@ -151,12 +153,12 @@ func unhandledError(err error) (*events.APIGatewayProxyResponse, error) { newErr = ErrInternalServer } + var r events.APIGatewayProxyResponse b, err := json.Marshal(newErr) if err != nil { - return nil, err + return r, err } - r := new(events.APIGatewayProxyResponse) r.Headers = make(map[string]string) r.Headers["Content-Type"] = "application/json" r.StatusCode = newErr.Status diff --git a/http_test.go b/http_test.go index fe83b10..65899a6 100644 --- a/http_test.go +++ b/http_test.go @@ -1,26 +1,27 @@ package g8_test import ( - "context" "fmt" - "github.com/aws/aws-lambda-go/events" - "github.com/stretchr/testify/assert" "net/http" "net/http/httptest" "testing" + "github.com/aws/aws-lambda-go/events" + "github.com/stretchr/testify/assert" + "github.com/JSainsburyPLC/g8" ) func TestLambdaAdapter(t *testing.T) { l := g8.LambdaHandler{ - Handler: func(ctx context.Context, r events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) { - return &events.APIGatewayProxyResponse{ + Handler: func(ctx *g8.APIGatewayProxyContext) error { + ctx.Response = events.APIGatewayProxyResponse{ StatusCode: http.StatusOK, Headers: map[string]string{"Content-Type": "text/plain"}, MultiValueHeaders: map[string][]string{"Set-Cookie": {"cookie1", "cookie2"}}, Body: "success", - }, nil + } + return nil }, Method: http.MethodGet, Path: "/test/url/path/{var1}/{var2}", @@ -40,12 +41,13 @@ func TestLambdaAdapter(t *testing.T) { func TestLambdaAdapter_without_content_type(t *testing.T) { l := g8.LambdaHandler{ - Handler: func(ctx context.Context, r events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) { - return &events.APIGatewayProxyResponse{ + Handler: func(ctx *g8.APIGatewayProxyContext) error { + ctx.Response = events.APIGatewayProxyResponse{ StatusCode: http.StatusOK, MultiValueHeaders: map[string][]string{"Set-Cookie": {"cookie1", "cookie2"}}, Body: `{"message":"success"}`, - }, nil + } + return nil }, Method: http.MethodGet, Path: "/test/url/path/{var1}/{var2}", @@ -64,8 +66,8 @@ func TestLambdaAdapter_without_content_type(t *testing.T) { func TestLambdaAdapter_g8_error(t *testing.T) { l := g8.LambdaHandler{ - Handler: func(ctx context.Context, r events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) { - return nil, g8.ErrInternalServer + Handler: func(ctx *g8.APIGatewayProxyContext) error { + return g8.ErrInternalServer }, Method: http.MethodGet, Path: "/test/url/path", @@ -83,8 +85,8 @@ func TestLambdaAdapter_g8_error(t *testing.T) { func TestLambdaAdapter_generic_error(t *testing.T) { l := g8.LambdaHandler{ - Handler: func(ctx context.Context, r events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) { - return nil, fmt.Errorf("generic error") + Handler: func(ctx *g8.APIGatewayProxyContext) error { + return fmt.Errorf("generic error") }, Method: http.MethodGet, Path: "/test/url/path",