Modified APIGHanlder function to only take one parameter that servces as

both request and response: APIGContext
This commit is contained in:
mitchelljfs 2018-07-17 14:01:18 -07:00
parent a84a71babb
commit e4134e6fd9
2 changed files with 39 additions and 45 deletions

View File

@ -17,28 +17,23 @@ const (
delete = http.MethodDelete delete = http.MethodDelete
) )
// APIGRequest is used as the input of handler functions. // APIGContext is used as the input and output of handler functions.
// The Claims, Path, and QryStr will be populated by the the APIGatewayProxyRequest. // The Body, Claims, Path, and QryStr will be populated by the the APIGatewayProxyRequest.
// The Request itself is also passed through if you need further access. // The Request itself is also passed through if you need further access.
type APIGRequest struct { // Fill the Status and Body, or Status and Error to respond.
Body string type APIGContext struct {
Claims map[string]interface{} Claims map[string]interface{}
Path map[string]string Path map[string]string
QryStr map[string]string QryStr map[string]string
Request *events.APIGatewayProxyRequest Request *events.APIGatewayProxyRequest
} Status int
Body []byte
// APIGResponse is used as the output of handler functions. Err error
// Populate Status and Body with your http response or populate Err with your error.
type APIGResponse struct {
Status int
Body []byte
Err error
} }
// APIGHandler is the interface a handler function must implement to be used // APIGHandler is the interface a handler function must implement to be used
// with Get, Post, Put, Patch, and Delete. // with Get, Post, Put, Patch, and Delete.
type APIGHandler func(req *APIGRequest, res *APIGResponse) type APIGHandler func(ctx *APIGContext)
// APIGRouter is the object that handlers build upon and is used in the end to respond. // APIGRouter is the object that handlers build upon and is used in the end to respond.
type APIGRouter struct { type APIGRouter struct {
@ -124,19 +119,18 @@ func (r *APIGRouter) Respond() events.APIGatewayProxyResponse {
handlers := handlersInterface.([]APIGHandler) handlers := handlersInterface.([]APIGHandler)
for _, handler := range handlers { for _, handler := range handlers {
req := &APIGRequest{ ctx := &APIGContext{
Body: r.request.Body, Body: []byte(r.request.Body),
Path: r.request.PathParameters, Path: r.request.PathParameters,
QryStr: r.request.QueryStringParameters, QryStr: r.request.QueryStringParameters,
Request: r.request, Request: r.request,
} }
if r.request.RequestContext.Authorizer["claims"] != nil { if r.request.RequestContext.Authorizer["claims"] != nil {
req.Claims = r.request.RequestContext.Authorizer["claims"].(map[string]interface{}) ctx.Claims = r.request.RequestContext.Authorizer["claims"].(map[string]interface{})
} }
res := &APIGResponse{}
handler(req, res) handler(ctx)
status, respbody, err = res.deconstruct() status, respbody, err = ctx.respDeconstruct()
if err != nil { if err != nil {
respbody, _ := json.Marshal(map[string]string{"error": err.Error()}) respbody, _ := json.Marshal(map[string]string{"error": err.Error()})
@ -164,8 +158,8 @@ func stripSlashesAndSplit(s string) []string {
return strings.Split(s, "/") return strings.Split(s, "/")
} }
func (res *APIGResponse) deconstruct() (int, []byte, error) { func (ctx *APIGContext) respDeconstruct() (int, []byte, error) {
return res.Status, res.Body, res.Err return ctx.Status, ctx.Body, ctx.Err
} }
func (r *APIGRouter) addEndpoint(method string, route string, handlers []APIGHandler) { func (r *APIGRouter) addEndpoint(method string, route string, handlers []APIGHandler) {

View File

@ -16,18 +16,18 @@ func TestRouterSpec(t *testing.T) {
rtr := NewAPIGRouter(&request, "shipping") rtr := NewAPIGRouter(&request, "shipping")
Convey("When the handler func does NOT return an error", func() { Convey("When the handler func does NOT return an error", func() {
hdlrfunc := func(req *APIGRequest, res *APIGResponse) { hdlrfunc := func(ctx *APIGContext) {
res.Status = http.StatusOK ctx.Status = http.StatusOK
res.Body = []byte("hello") ctx.Body = []byte("hello")
res.Err = nil ctx.Err = nil
} }
Convey("And a Get handler expecting the pattern /orders/filter/by_user/{id} is defined", func() { Convey("And a Get handler expecting the pattern /orders/filter/by_user/{id} is defined", func() {
rtr.Get("/orders/filter/by_user/{id}", hdlrfunc) rtr.Get("/orders/filter/by_user/{id}", hdlrfunc)
rtr.Post("/orders", func(req *APIGRequest, res *APIGResponse) {}) rtr.Post("/orders", func(ctx *APIGContext) {})
rtr.Put("/orders", func(req *APIGRequest, res *APIGResponse) {}) rtr.Put("/orders", func(ctx *APIGContext) {})
rtr.Patch("/orders", func(req *APIGRequest, res *APIGResponse) {}) rtr.Patch("/orders", func(ctx *APIGContext) {})
rtr.Delete("/orders/{id}", func(req *APIGRequest, res *APIGResponse) {}) rtr.Delete("/orders/{id}", func(ctx *APIGContext) {})
Convey("And the request matches the pattern and the path params are filled", func() { Convey("And the request matches the pattern and the path params are filled", func() {
request.HTTPMethod = http.MethodGet request.HTTPMethod = http.MethodGet
@ -99,10 +99,10 @@ func TestRouterSpec(t *testing.T) {
}) })
Convey("When the handler func does return a record not found", func() { Convey("When the handler func does return a record not found", func() {
hdlrfunc := func(req *APIGRequest, res *APIGResponse) { hdlrfunc := func(ctx *APIGContext) {
res.Status = http.StatusBadRequest ctx.Status = http.StatusBadRequest
res.Body = []byte("hello") ctx.Body = []byte("hello")
res.Err = errors.New("record not found") ctx.Err = errors.New("record not found")
} }
@ -127,20 +127,20 @@ func TestRouterSpec(t *testing.T) {
}) })
Convey("When the handler func does return a status < 400", func() { Convey("When the handler func does return a status < 400", func() {
middlefunc1 := func(req *APIGRequest, res *APIGResponse) { middlefunc1 := func(ctx *APIGContext) {
res.Status = http.StatusOK ctx.Status = http.StatusOK
res.Body = []byte("hello") ctx.Body = []byte("hello")
res.Err = nil ctx.Err = nil
} }
middlefunc2 := func(req *APIGRequest, res *APIGResponse) { middlefunc2 := func(ctx *APIGContext) {
res.Status = http.StatusOK ctx.Status = http.StatusOK
res.Body = []byte("hello") ctx.Body = []byte("hello")
res.Err = errors.New("bad request") ctx.Err = errors.New("bad request")
} }
hdlrfunc := func(req *APIGRequest, res *APIGResponse) { hdlrfunc := func(ctx *APIGContext) {
res.Status = http.StatusOK ctx.Status = http.StatusOK
res.Body = []byte("hello") ctx.Body = []byte("hello")
res.Err = nil ctx.Err = nil
} }
Convey("And a Get handler expecting the pattern /orders/filter/by_user/{id} is defined", func() { Convey("And a Get handler expecting the pattern /orders/filter/by_user/{id} is defined", func() {