-
Notifications
You must be signed in to change notification settings - Fork 0
/
ginlambda.go
84 lines (69 loc) · 2.32 KB
/
ginlambda.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package ginlambda
import (
"context"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/gin-gonic/gin"
)
// HandlerFunc is the signature for the Lambda handler function.
type HandlerFunc func(context.Context, events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)
// Start is analogous to lambda.Start() but takes a *gin.Engine argument instead of a handler
// function. The engine should have any desired routes initialized but should not be run.
func Start(r *gin.Engine) {
handler := NewHandler(r)
lambda.Start(handler)
}
// NewHandler creates a new Lambda handler function from a *gin.Engine instance. This handler may
// be passed as the handler argument to lambda.Start().
func NewHandler(r *gin.Engine) HandlerFunc {
return func(ctx context.Context,
request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
httpRequest, useMultiValueHeader, err := constructHTTPRequestFromAPIRequest(ctx, request)
if err != nil {
return events.APIGatewayProxyResponse{}, err
}
collector := newAPIResponseCollector(useMultiValueHeader)
r.ServeHTTP(collector, httpRequest)
return collector.ToAPIGatewayProxyResponse(), nil
}
}
func constructHTTPRequestFromAPIRequest(
ctx context.Context, request events.APIGatewayProxyRequest) (*http.Request, bool, error) {
useMultiValueHeader := (request.Headers == nil)
// initialize request query
var queryStr string
if useMultiValueHeader {
queryStr = url.Values(request.MultiValueQueryStringParameters).Encode()
} else {
queryValues := make(url.Values)
for k, v := range request.QueryStringParameters {
queryValues.Set(k, v)
}
queryStr = queryValues.Encode()
}
// initialize request with context
reader := ioutil.NopCloser(strings.NewReader(request.Body))
fullPath := fmt.Sprintf("%s?%s", request.Path, queryStr)
httpRequest, err := http.NewRequestWithContext(ctx, request.HTTPMethod, fullPath, reader)
if err != nil {
return nil, false, err
}
// initialize request header
if useMultiValueHeader {
for k, vs := range request.MultiValueHeaders {
for _, v := range vs {
httpRequest.Header.Add(k, v)
}
}
} else {
for k, v := range request.Headers {
httpRequest.Header.Set(k, v)
}
}
return httpRequest, useMultiValueHeader, nil
}