Select Git revision
lambda.go 8.24 KiB
package api
import (
"context"
"encoding/json"
"fmt"
"math/rand"
"net/http"
"reflect"
"time"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambdacontext"
"gitlab.com/uafrica/go-utils/errors"
"gitlab.com/uafrica/go-utils/service"
)
//this is native handler for lambda passed into lambda.Start()
//to run locally, this is called from app.ServeHTTP()
func (api Api) Handler(baseCtx context.Context, apiGatewayProxyReq events.APIGatewayProxyRequest) (res events.APIGatewayProxyResponse, err error) {
res = events.APIGatewayProxyResponse{
StatusCode: http.StatusInternalServerError,
Body: "undefined response",
Headers: map[string]string{},
}
// Replace the proxy resource with the path, has some edge cases but works for our current API implementation
// Edge case being that if have path params then specify those routes explicitly
if apiGatewayProxyReq.Resource == "/{proxy+}" {
apiGatewayProxyReq.Resource = apiGatewayProxyReq.Path
}
//setup context
requestID := apiGatewayProxyReq.RequestContext.RequestID
if lambdaContext, ok := lambdacontext.FromContext(baseCtx); ok && lambdaContext != nil {
requestID = lambdaContext.AwsRequestID
}
ctx := Context{
Context: service.NewContext(baseCtx, map[string]interface{}{
"env": api.env,
"request_id": requestID,
}),
IProducer: api.producer,
Request: apiGatewayProxyReq,
RequestID: requestID,
ValuesFromChecks: map[string]map[string]interface{}{},
}
//report handler crashes
defer api.crashReporter.Catch(ctx)
defer func() {
//set CORS headers on every response
if api.cors != nil {
for n, v := range api.cors.CORS() {
res.Headers[n] = v
}
}
}()
defer func() {
ctx.LogAPIRequestAndResponse(res, err)
if err != nil {
if withCause, ok := err.(errors.ErrorWithCause); ok && withCause.Code() != 0 {
res.StatusCode = withCause.Code()
}
errorMessage := fmt.Sprintf("%c", err)
jsonError, _ := json.Marshal(map[string]interface{}{"message": errorMessage})
res.Body = string(jsonError)
err = nil //never pass error back to lambda or http server