Skip to content

Commit 196b8d3

Browse files
author
Dana H. P'Simer, Jr
committed
added support for aws go runtime
1 parent d8e8c6a commit 196b8d3

File tree

12 files changed

+227
-74
lines changed

12 files changed

+227
-74
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@ _testmain.go
2929
.idea
3030

3131
examples/helloWorld/helloWorld
32+
examples/helloWorld/aws/handler
33+

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[submodule "vendor/github.com/aws/aws-lambda-go"]
2+
path = vendor/github.com/aws/aws-lambda-go
3+
url = https://github.com/aws/aws-lambda-go
4+
[submodule "vendor/github.com/eawsy/aws-lambda-go"]
5+
path = vendor/github.com/eawsy/aws-lambda-go
6+
url = https://github.com/eawsy/aws-lambda-go

Readme.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ The basic steps for usage are as follows:
5252
log.Fatal(http.ListenAndServe(":8080", handler))
5353
}
5454
```
55-
3. create your main() for your lambda:
55+
3. create your main() for your eawsy:
5656

5757
```go
5858
package main
@@ -69,7 +69,7 @@ The basic steps for usage are as follows:
6969
func main() {
7070
}
7171
```
72-
4. Make your lambda:
72+
4. Make your eawsy:
7373

7474
```Makefile
7575
build:
@@ -80,7 +80,7 @@ The basic steps for usage are as follows:
8080
zip handler.zip handler.so
8181
chown `stat -c "%u:%g" .` handler.zip
8282
```
83-
5. Create your lambda in AWS: (in the directory your lambda handler was built)
83+
5. Create your eawsy in AWS: (in the directory your eawsy handler was built)
8484

8585
```bash
8686
aws lambda create-function \

aws/shim.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package aws
2+
3+
import (
4+
"encoding/base64"
5+
"fmt"
6+
"github.com/aws/aws-lambda-go/events"
7+
"github.com/aws/aws-lambda-go/lambda"
8+
"github.com/danapsimer/aws-api-to-lambda-shim/utils"
9+
"io"
10+
"io/ioutil"
11+
"log"
12+
"net/http"
13+
"net/url"
14+
"strings"
15+
"context"
16+
)
17+
18+
type ShimInitFunc func() (http.Handler, error)
19+
20+
type HttpHandlerShim struct {
21+
init ShimInitFunc
22+
initCalled bool
23+
handler http.Handler
24+
}
25+
26+
func NewHttpHandlerShim(init ShimInitFunc) (*HttpHandlerShim, error) {
27+
shim := &HttpHandlerShim{
28+
init: init,
29+
initCalled: false,
30+
handler: nil,
31+
}
32+
lambda.Start(func(ctx context.Context,evt events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
33+
return shim.handle(ctx, evt)
34+
})
35+
return shim, nil
36+
}
37+
38+
func (shim *HttpHandlerShim) handle(ctx context.Context,request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
39+
if !shim.initCalled {
40+
handler, err := shim.init()
41+
if err != nil {
42+
log.Printf("ERROR: %s", err.Error())
43+
return events.APIGatewayProxyResponse{StatusCode: 500, Body: err.Error()}, err
44+
}
45+
shim.handler = handler
46+
shim.initCalled = true
47+
}
48+
49+
var urlStr string
50+
if len(request.QueryStringParameters) != 0 {
51+
urlStr = fmt.Sprintf("%s?%s", request.Path, utils.QueryStringParams2Values(request.QueryStringParameters).Encode())
52+
} else {
53+
urlStr = request.Path
54+
}
55+
url, err := url.ParseRequestURI(urlStr)
56+
if err != nil {
57+
log.Printf("ERROR: %s", err.Error())
58+
return events.APIGatewayProxyResponse{StatusCode: 500, Body: err.Error()}, err
59+
}
60+
var bodyReader io.Reader
61+
bodyReader = strings.NewReader(request.Body)
62+
if request.IsBase64Encoded {
63+
bodyReader = base64.NewDecoder(base64.StdEncoding, bodyReader)
64+
}
65+
httpRequest := http.Request{
66+
Method: request.HTTPMethod,
67+
URL: url,
68+
Proto: "HTTP/1.0",
69+
ProtoMajor: 1,
70+
ProtoMinor: 0,
71+
Header: utils.Headers2Header(request.Headers),
72+
Body: ioutil.NopCloser(bodyReader),
73+
ContentLength: int64(len(request.Body)),
74+
Close: false,
75+
Host: request.Headers["Host"],
76+
RemoteAddr: request.Headers["Host"],
77+
RequestURI: url.String(),
78+
}
79+
responseWriter, err := utils.NewLambdaResponseWriter()
80+
if err != nil {
81+
log.Printf("ERROR: %s", err.Error())
82+
return events.APIGatewayProxyResponse{StatusCode: 500, Body: err.Error()}, nil
83+
}
84+
shim.handler.ServeHTTP(responseWriter, httpRequest.WithContext(ctx))
85+
if responseWriter.ResponseBuffer.Len() > 0 {
86+
if _, hasContentType := responseWriter.Header()["Content-Type"]; !hasContentType {
87+
responseWriter.Header().Add("Content-Type", http.DetectContentType(responseWriter.ResponseBuffer.Bytes()))
88+
}
89+
}
90+
responseBody := responseWriter.ResponseBuffer.String()
91+
response := events.APIGatewayProxyResponse{
92+
StatusCode: int(responseWriter.StatusCode),
93+
Body: responseBody,
94+
Headers: utils.Header2Headers(responseWriter.Header()),
95+
}
96+
return response, nil
97+
}

shim/shim.go renamed to eawsy/shim.go

Lines changed: 7 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
package shim
1+
package eawsy
22

33
import (
4-
"bytes"
4+
"encoding/base64"
55
"encoding/json"
66
"fmt"
7+
"github.com/danapsimer/aws-api-to-lambda-shim/utils"
78
"github.com/eawsy/aws-lambda-go/service/lambda/runtime"
89
"io"
910
"io/ioutil"
1011
"log"
1112
"net/http"
1213
"net/url"
1314
"strings"
14-
"encoding/base64"
1515
)
1616

1717
type ShimInitFunc func() (http.Handler, error)
@@ -78,68 +78,6 @@ type apiGatewayResponse struct {
7878
Body string `json:"body,omitempty"`
7979
}
8080

81-
type lambdaResponseWriter struct {
82-
header http.Header
83-
StatusCode int
84-
ResponseBuffer bytes.Buffer
85-
}
86-
87-
func NewLambdaResponseWriter() (*lambdaResponseWriter, error) {
88-
return &lambdaResponseWriter{
89-
header: make(map[string][]string),
90-
StatusCode: 0,
91-
}, nil
92-
}
93-
94-
func (w *lambdaResponseWriter) Header() http.Header {
95-
return w.header
96-
}
97-
98-
func (w *lambdaResponseWriter) Write(bytes []byte) (int, error) {
99-
if w.StatusCode == 0 {
100-
w.StatusCode = 200
101-
}
102-
bytesWritten, err := w.ResponseBuffer.Write(bytes)
103-
return bytesWritten, err
104-
}
105-
106-
func (w *lambdaResponseWriter) WriteHeader(statusCode int) {
107-
w.StatusCode = statusCode
108-
}
109-
110-
func queryStringParams2Values(qsp map[string]string) url.Values {
111-
if qsp == nil {
112-
return nil
113-
}
114-
values := url.Values{}
115-
for k, v := range qsp {
116-
values.Add(k, v)
117-
}
118-
return values
119-
}
120-
121-
func headers2Header(headers map[string]string) http.Header {
122-
if headers == nil {
123-
return nil
124-
}
125-
values := http.Header{}
126-
for k, v := range headers {
127-
values.Add(k, v)
128-
}
129-
return values
130-
}
131-
132-
func header2Headers(header http.Header) map[string]string {
133-
if header == nil {
134-
return nil
135-
}
136-
values := make(map[string]string)
137-
for k, v := range header {
138-
values[k] = v[0]
139-
}
140-
return values
141-
}
142-
14381
func (shim *HttpHandlerShim) handle(evt json.RawMessage, ctx *runtime.Context) (interface{}, error) {
14482
if !shim.initCalled {
14583
handler, err := shim.init()
@@ -161,7 +99,7 @@ func (shim *HttpHandlerShim) handle(evt json.RawMessage, ctx *runtime.Context) (
16199

162100
var urlStr string
163101
if len(msg.QueryStringParameters) != 0 {
164-
urlStr = fmt.Sprintf("%s?%s", msg.Path, queryStringParams2Values(msg.QueryStringParameters).Encode())
102+
urlStr = fmt.Sprintf("%s?%s", msg.Path, utils.QueryStringParams2Values(msg.QueryStringParameters).Encode())
165103
} else {
166104
urlStr = msg.Path
167105
}
@@ -182,7 +120,7 @@ func (shim *HttpHandlerShim) handle(evt json.RawMessage, ctx *runtime.Context) (
182120
Proto: "HTTP/1.0",
183121
ProtoMajor: 1,
184122
ProtoMinor: 0,
185-
Header: headers2Header(msg.Headers),
123+
Header: utils.Headers2Header(msg.Headers),
186124
Body: ioutil.NopCloser(bodyReader),
187125
ContentLength: int64(len(msg.Body)),
188126
Close: false,
@@ -191,7 +129,7 @@ func (shim *HttpHandlerShim) handle(evt json.RawMessage, ctx *runtime.Context) (
191129
RequestURI: url.String(),
192130
}
193131
//log.Printf("httpRequest created: %v", &httpRequest)
194-
responseWriter, err := NewLambdaResponseWriter()
132+
responseWriter, err := utils.NewLambdaResponseWriter()
195133
if err != nil {
196134
log.Printf("ERROR: %s", err.Error())
197135
return apiGatewayResponse{StatusCode: 500, Body: err.Error()}, nil
@@ -207,7 +145,7 @@ func (shim *HttpHandlerShim) handle(evt json.RawMessage, ctx *runtime.Context) (
207145
response := apiGatewayResponse{
208146
StatusCode: int32(responseWriter.StatusCode),
209147
Body: responseBody,
210-
Headers: header2Headers(responseWriter.Header()),
148+
Headers: utils.Header2Headers(responseWriter.Header()),
211149
}
212150
//log.Printf("Response: %v", &response)
213151
return &response, nil

examples/helloWorld/aws/Makefile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
AWS_ACCOUNT_ID := $(shell aws iam get-user | jq -r '.User.Arn' | cut -d : -f 5)
2+
$(info AWS_ACCOUNT_ID = '$(AWS_ACCOUNT_ID)')
3+
4+
AWS_ROLE := arn:aws:iam::$(AWS_ACCOUNT_ID):role/lambda_basic_execution
5+
6+
build:
7+
GOOS=linux go build -o handler
8+
9+
pack:
10+
zip handler.zip handler
11+
12+
clean:
13+
@rm -rf handler.zip handler
14+
15+
create:
16+
@aws lambda create-function \
17+
--region us-east-1 \
18+
--function-name hello-world-api-go \
19+
--zip-file fileb://handler.zip \
20+
--runtime go1.x \
21+
--role $(AWS_ROLE) \
22+
--handler handler
23+
24+
update:
25+
@aws lambda update-function-code --function-name hello-world-api-go --zip-file fileb://handler.zip

examples/helloWorld/lambda/handler.go renamed to examples/helloWorld/aws/handler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ package main
22

33
import (
44
"github.com/danapsimer/aws-api-to-lambda-shim/examples/helloWorld/hello"
5-
"github.com/danapsimer/aws-api-to-lambda-shim/shim"
5+
"github.com/danapsimer/aws-api-to-lambda-shim/aws"
66
)
77

88
func init() {
9-
shim.NewHttpHandlerShim(hello.InitHandler)
9+
aws.NewHttpHandlerShim(hello.InitHandler)
1010
}
1111

1212
func main() {

examples/helloWorld/eawsy/handler.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package main
2+
3+
import (
4+
"github.com/danapsimer/aws-api-to-lambda-shim/examples/helloWorld/hello"
5+
"github.com/danapsimer/aws-api-to-lambda-shim/eawsy"
6+
)
7+
8+
func init() {
9+
eawsy.NewHttpHandlerShim(hello.InitHandler)
10+
}
11+
12+
func main() {
13+
}

utils/adapters.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package utils
2+
3+
import (
4+
"bytes"
5+
"net/url"
6+
"net/http"
7+
)
8+
9+
type lambdaResponseWriter struct {
10+
header http.Header
11+
StatusCode int
12+
ResponseBuffer bytes.Buffer
13+
}
14+
15+
func NewLambdaResponseWriter() (*lambdaResponseWriter, error) {
16+
return &lambdaResponseWriter{
17+
header: make(map[string][]string),
18+
StatusCode: 0,
19+
}, nil
20+
}
21+
22+
func (w *lambdaResponseWriter) Header() http.Header {
23+
return w.header
24+
}
25+
26+
func (w *lambdaResponseWriter) Write(bytes []byte) (int, error) {
27+
if w.StatusCode == 0 {
28+
w.StatusCode = 200
29+
}
30+
bytesWritten, err := w.ResponseBuffer.Write(bytes)
31+
return bytesWritten, err
32+
}
33+
34+
func (w *lambdaResponseWriter) WriteHeader(statusCode int) {
35+
w.StatusCode = statusCode
36+
}
37+
38+
func QueryStringParams2Values(qsp map[string]string) url.Values {
39+
if qsp == nil {
40+
return nil
41+
}
42+
values := url.Values{}
43+
for k, v := range qsp {
44+
values.Add(k, v)
45+
}
46+
return values
47+
}
48+
49+
func Headers2Header(headers map[string]string) http.Header {
50+
if headers == nil {
51+
return nil
52+
}
53+
values := http.Header{}
54+
for k, v := range headers {
55+
values.Add(k, v)
56+
}
57+
return values
58+
}
59+
60+
func Header2Headers(header http.Header) map[string]string {
61+
if header == nil {
62+
return nil
63+
}
64+
values := make(map[string]string)
65+
for k, v := range header {
66+
values[k] = v[0]
67+
}
68+
return values
69+
}
70+

vendor/github.com/aws/aws-lambda-go

Submodule aws-lambda-go added at 4013798

vendor/github.com/eawsy/aws-lambda-go

Submodule aws-lambda-go added at d67ea54

0 commit comments

Comments
 (0)