Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

g8 http server migration #17

Merged
merged 1 commit into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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