forked from mweagle/Sparta
-
Notifications
You must be signed in to change notification settings - Fork 0
/
response.go
108 lines (98 loc) · 3.22 KB
/
response.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
96
97
98
99
100
101
102
103
104
105
106
107
108
package apigateway
import (
"encoding/json"
"fmt"
"net/http"
"strings"
)
// Error represents an error to return in response to an
// API Gateway request.
type Error struct {
Code int `json:"code"`
Err string `json:"err"`
Message string `json:"message"`
Context map[string]interface{} `json:"context,omitempty"`
}
// Error returns the JSONified version of this error which will
// trigger the appropriate integration mapping.
func (apigError *Error) Error() string {
bytes, bytesErr := json.Marshal(apigError)
if bytesErr != nil {
bytes = []byte(http.StatusText(http.StatusInternalServerError))
}
return string(bytes)
}
// NewErrorResponse returns a response that satisfies
// the regular expression used to determine integration mappings
// via the API Gateway. messages is a stringable type. Error interface
// instances will be properly typecast.
func NewErrorResponse(statusCode int, messages ...interface{}) *Error {
additionalMessages := make([]string, len(messages))
for eachIndex, eachMessage := range messages {
switch typedValue := eachMessage.(type) {
case error:
additionalMessages[eachIndex] = typedValue.Error()
default:
additionalMessages[eachIndex] = fmt.Sprintf("%v", typedValue)
}
}
err := &Error{
Code: statusCode,
Err: http.StatusText(statusCode),
Message: strings.Join(additionalMessages, " "),
Context: make(map[string]interface{}),
}
if len(err.Err) <= 0 {
err.Code = http.StatusInternalServerError
err.Err = http.StatusText(http.StatusInternalServerError)
}
return err
}
// Response is the type returned by an API Gateway function. Note that a
// non 2xx HTTP status code should be returned as a Response
// type rather than an Error. Errors should be reserved for Lambda
// functions that fail to execute.
type Response struct {
Code int `json:"code,omitempty"`
Body interface{} `json:"body,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
}
// canonicalResponse is the type for the canonicalized response with the
// headers lowercased to match any API-Gateway case sensitive whitelist
// matching
type canonicalResponse struct {
Code int `json:"code,omitempty"`
Body interface{} `json:"body,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
}
// MarshalJSON is a custom marshaller to ensure that the marshalled
// headers are always lowercase
func (resp *Response) MarshalJSON() ([]byte, error) {
canonicalResponse := canonicalResponse{
Code: resp.Code,
Body: resp.Body,
}
if len(resp.Headers) != 0 {
canonicalResponse.Headers = make(map[string]string)
for eachKey, eachValue := range resp.Headers {
canonicalResponse.Headers[strings.ToLower(eachKey)] = eachValue
}
}
return json.Marshal(&canonicalResponse)
}
// NewResponse returns an API Gateway response object
func NewResponse(code int, body interface{}, headers ...map[string]string) *Response {
response := &Response{
Code: code,
Body: body,
}
if len(headers) != 0 {
response.Headers = make(map[string]string)
for _, eachHeaderMap := range headers {
for eachKey, eachValue := range eachHeaderMap {
response.Headers[eachKey] = eachValue
}
}
}
return response
}