forked from abiosoft/caddy-exec
-
Notifications
You must be signed in to change notification settings - Fork 0
/
req_resp.go
123 lines (108 loc) · 3.4 KB
/
req_resp.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package caddyawslambda
import (
"encoding/json"
"io/ioutil"
"net/http"
"strings"
)
// parseReply unpacks the Lambda response data into a Reply.
// If the reply is a JSON object with a 'type' field equal to 'HTTPJSON-REP', then
// data will be unmarshaled directly as a Reply struct.
//
// If data is not a JSON object, or the object's type field is omitted or set to
// a string other than 'HTTPJSON-REP', then data will be set as the Reply.body
// and Reply.meta will contain a default struct with a 200 status and
// a content-type header of 'application/json'.
func parseReply(data []byte) (*Reply, error) {
if len(data) > 0 && data[0] == '{' {
var rep Reply
err := json.Unmarshal(data, &rep)
if err == nil && rep.Type == "HTTPJSON-REP" {
if rep.Meta == nil {
rep.Meta = &defaultMeta
}
return &rep, nil
}
}
return &Reply{
Type: "HTTPJSON-REP",
Meta: &defaultMeta,
Body: string(data),
}, nil
}
// newRequest returns a new Request based on the HTTP request.
// Returns an error if the HTTP request body cannot be read.
func newRequest(r *http.Request) (*Request, error) {
defer r.Body.Close()
body, err := ioutil.ReadAll(r.Body)
if err != nil {
return nil, err
}
return &Request{
Type: "HTTPJSON-REQ",
Meta: newRequestMeta(r),
Body: string(body),
}, nil
}
// newRequestMeta returns a new RequestMeta based on the HTTP request
func newRequestMeta(r *http.Request) *RequestMeta {
headers := make(map[string][]string)
for k, v := range r.Header {
headers[strings.ToLower(k)] = v
}
return &RequestMeta{
Method: r.Method,
Path: r.URL.Path,
Query: r.URL.RawQuery,
Host: r.Host,
Proto: r.Proto,
Headers: headers,
}
}
// Request represents a single HTTP request. It will be serialized as JSON
// and sent to the AWS Lambda function as the function payload.
type Request struct {
// Set to the constant "HTTPJSON-REQ"
Type string `json:"type"`
// Metadata about the HTTP request
Meta *RequestMeta `json:"meta"`
// HTTP request body (may be empty)
Body string `json:"body"`
}
// RequestMeta represents HTTP metadata present on the request
type RequestMeta struct {
// HTTP method used by client (e.g. GET or POST)
Method string `json:"method"`
// Path portion of URL without the query string
Path string `json:"path"`
// Query string (without '?')
Query string `json:"query"`
// Host field from net/http Request, which may be of the form host:port
Host string `json:"host"`
// Proto field from net/http Request, for example "HTTP/1.1"
Proto string `json:"proto"`
// HTTP request headers
Headers map[string][]string `json:"headers"`
}
// Reply encapsulates the response from a Lambda invocation.
// AWS Lambda functions should return a JSON object that matches this format.
type Reply struct {
// Must be set to the constant "HTTPJSON-REP"
Type string `json:"type"`
// Reply metadata. If omitted, a default 200 status with empty headers will be used.
Meta *ReplyMeta `json:"meta"`
// Response body
Body string `json:"body"`
// Encoding of Body - Valid values: "", "base64"
BodyEncoding string `json:"bodyEncoding"`
}
// ReplyMeta encapsulates HTTP response metadata that the lambda function wishes
// Caddy to set on the HTTP response.
//
// *NOTE* that header values must be encoded as string arrays
type ReplyMeta struct {
// HTTP status code (e.g. 200 or 404)
Status int `json:"status"`
// HTTP response headers
Headers map[string][]string `json:"headers"`
}