forked from aws/aws-sam-cli
-
Notifications
You must be signed in to change notification settings - Fork 6
/
mount.go
95 lines (82 loc) · 2.62 KB
/
mount.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
85
86
87
88
89
90
91
92
93
94
95
package router
import (
"encoding/base64"
"io/ioutil"
"mime"
"net/http"
"strings"
"unicode/utf8"
"log"
"fmt"
)
const MuxPathRegex = ".+"
var HttpMethods = []string{"OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"}
// EventHandlerFunc is similar to Go http.Handler but it receives an event from API Gateway
// instead of http.Request
type EventHandlerFunc func(http.ResponseWriter, *Event)
// ServerlessRouterMount represents a single mount point on the API
// Such as '/path', the HTTP method, and the function to resolve it
type ServerlessRouterMount struct {
Name string
Function *AWSServerlessFunction
Handler EventHandlerFunc
Path string
Method string
BinaryMediaTypes []string
// authorization settings
AuthType string
AuthFunction *AWSServerlessFunction
IntegrationArn *LambdaFunctionArn
}
// Returns the wrapped handler to encode the body as base64 when binary
// media types contains Content-Type
func (m *ServerlessRouterMount) WrappedHandler() http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
contentType := req.Header.Get("Content-Type")
mediaType, _, err := mime.ParseMediaType(contentType)
binaryContent := false
if err == nil {
for _, value := range m.BinaryMediaTypes {
if value != "" && value == mediaType {
binaryContent = true
break
}
}
}
if binaryContent {
if body, err := ioutil.ReadAll(req.Body); err == nil && !utf8.Valid(body) {
req.Body = ioutil.NopCloser(strings.NewReader(base64.StdEncoding.EncodeToString(body)))
} else {
req.Body = ioutil.NopCloser(strings.NewReader(string(body)))
}
}
event, err := NewEvent(req, binaryContent)
if err != nil {
msg := fmt.Sprintf("Error creating a new event: %s", err)
log.Println(msg)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(`{ "message": "Internal server error" }`))
} else {
m.Handler(w, event)
}
})
}
// Methods gets an array of HTTP methods from a AWS::Serverless::Function
// API event source method declaration (which could include 'any')
func (m *ServerlessRouterMount) Methods() []string {
switch strings.ToUpper(m.Method) {
case "ANY":
return HttpMethods
default:
return []string{strings.ToUpper(m.Method)}
}
}
// Returns the mount path adjusted for mux syntax. For example, if the
// SAM template specifies /{proxy+} we replace that with /{proxy:.*}
func (m *ServerlessRouterMount) GetMuxPath() string {
outputPath := m.Path
if strings.Contains(outputPath, "+") {
outputPath = strings.Replace(outputPath, "+", ":" + MuxPathRegex, -1)
}
return outputPath
}