Skip to content

Commit

Permalink
g8 http server migration (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
jfallis authored Sep 20, 2023
1 parent 6518cbe commit a810834
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 36 deletions.
48 changes: 25 additions & 23 deletions http.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
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
}

// 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))
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down
28 changes: 15 additions & 13 deletions http_test.go
Original file line number Diff line number Diff line change
@@ -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}",
Expand All @@ -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}",
Expand All @@ -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",
Expand All @@ -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",
Expand Down

0 comments on commit a810834

Please sign in to comment.