Skip to content

Commit 8c74d92

Browse files
committed
addunittests
1 parent 9755d5c commit 8c74d92

7 files changed

+313
-654
lines changed

Diff for: core/requestFunctionUrl.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ const (
2626
FuContextHeader = "X-GoLambdaProxy-Fu-Context"
2727
)
2828

29-
// RequestAccessorV2 objects give access to custom API Gateway properties
29+
// RequestAccessorFu objects give access to custom API Gateway properties
3030
// in the request.
3131
type RequestAccessorFu struct {
3232
stripBasePath string
3333
}
3434

35-
// GetAPIGatewayContextV2 extracts the API Gateway context object from a
35+
// GetFunctionUrlContext extracts the API Gateway context object from a
3636
// request's custom header.
37-
// Returns a populated events.APIGatewayProxyRequestContext object from
37+
// Returns a populated events.LambdaFunctionURLRequestContext object from
3838
// the request.
3939
func (r *RequestAccessorFu) GetFunctionUrlContext(req *http.Request) (events.LambdaFunctionURLRequestContext, error) {
4040
if req.Header.Get(APIGwContextHeader) == "" {
@@ -74,9 +74,9 @@ func (r *RequestAccessorFu) StripBasePath(basePath string) string {
7474
return newBasePath
7575
}
7676

77-
// ProxyEventToHTTPRequest converts an API Gateway proxy event into a http.Request object.
78-
// Returns the populated http request with additional two custom headers for the stage variables and API Gateway context.
79-
// To access these properties use the GetAPIGatewayStageVars and GetAPIGatewayContext method of the RequestAccessor object.
77+
// ProxyEventToHTTPRequest converts an Function URL proxy event into a http.Request object.
78+
// Returns the populated http request with additional two custom headers for the stage variables and Function Url context.
79+
// To access these properties use GetFunctionUrlContext method of the RequestAccessor object.
8080
func (r *RequestAccessorFu) ProxyEventToHTTPRequest(req events.LambdaFunctionURLRequest) (*http.Request, error) {
8181
httpRequest, err := r.EventToRequest(req)
8282
if err != nil {
@@ -86,9 +86,9 @@ func (r *RequestAccessorFu) ProxyEventToHTTPRequest(req events.LambdaFunctionURL
8686
return addToHeaderFu(httpRequest, req)
8787
}
8888

89-
// EventToRequestWithContext converts an API Gateway proxy event and context into an http.Request object.
89+
// EventToRequestWithContext converts an Function URL proxy event and context into an http.Request object.
9090
// Returns the populated http request with lambda context, stage variables and APIGatewayProxyRequestContext as part of its context.
91-
// Access those using GetAPIGatewayContextFromContext, GetStageVarsFromContext and GetRuntimeContextFromContext functions in this package.
91+
// Access those using GetFunctionUrlContextFromContext and GetRuntimeContextFromContext functions in this package.
9292
func (r *RequestAccessorFu) EventToRequestWithContext(ctx context.Context, req events.LambdaFunctionURLRequest) (*http.Request, error) {
9393
httpRequest, err := r.EventToRequest(req)
9494
if err != nil {
@@ -98,7 +98,7 @@ func (r *RequestAccessorFu) EventToRequestWithContext(ctx context.Context, req e
9898
return addToContextFu(ctx, httpRequest, req), nil
9999
}
100100

101-
// EventToRequest converts an API Gateway proxy event into an http.Request object.
101+
// EventToRequest converts an Function URL proxy event into an http.Request object.
102102
// Returns the populated request maintaining headers
103103
func (r *RequestAccessorFu) EventToRequest(req events.LambdaFunctionURLRequest) (*http.Request, error) {
104104
decodedBody := []byte(req.Body)
@@ -111,7 +111,6 @@ func (r *RequestAccessorFu) EventToRequest(req events.LambdaFunctionURLRequest)
111111
}
112112

113113
path := req.RawPath
114-
115114
// if RawPath empty is, populate from request context
116115
if len(path) == 0 {
117116
path = req.RequestContext.HTTP.Path
@@ -121,6 +120,7 @@ func (r *RequestAccessorFu) EventToRequest(req events.LambdaFunctionURLRequest)
121120
if strings.HasPrefix(path, r.stripBasePath) {
122121
path = strings.Replace(path, r.stripBasePath, "", 1)
123122
}
123+
fmt.Printf("%v", path)
124124
}
125125
if !strings.HasPrefix(path, "/") {
126126
path = "/" + path
@@ -187,13 +187,13 @@ func addToContextFu(ctx context.Context, req *http.Request, functionUrlRequest e
187187
return req.WithContext(ctx)
188188
}
189189

190-
// GetAPIGatewayV2ContextFromContext retrieve APIGatewayProxyRequestContext from context.Context
190+
// GetFunctionUrlContextFromContext retrieve APIGatewayProxyRequestContext from context.Context
191191
func GetFunctionUrlContextFromContext(ctx context.Context) (events.LambdaFunctionURLRequestContext, bool) {
192192
v, ok := ctx.Value(ctxKey{}).(requestContextFu)
193193
return v.functionUrlProxyContext, ok
194194
}
195195

196-
// GetRuntimeContextFromContextV2 retrieve Lambda Runtime Context from context.Context
196+
// GetRuntimeContextFromContextFu retrieve Lambda Runtime Context from context.Context
197197
func GetRuntimeContextFromContextFu(ctx context.Context) (*lambdacontext.LambdaContext, bool) {
198198
v, ok := ctx.Value(ctxKey{}).(requestContextFu)
199199
return v.lambdaContext, ok

Diff for: core/requestFunctionUrl_test.go

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package core_test
2+
3+
import (
4+
"context"
5+
"crypto/rand"
6+
"encoding/base64"
7+
"fmt"
8+
9+
"github.com/aws/aws-lambda-go/events"
10+
"github.com/awslabs/aws-lambda-go-api-proxy/core"
11+
. "github.com/onsi/ginkgo"
12+
. "github.com/onsi/gomega"
13+
)
14+
15+
var _ = Describe("RequestAccessorFu tests", func() {
16+
Context("Function URL event conversion", func() {
17+
accessor := core.RequestAccessorFu{}
18+
qs := make(map[string]string)
19+
mvqs := make(map[string][]string)
20+
hdr := make(map[string]string)
21+
qs["UniqueId"] = "12345"
22+
hdr["header1"] = "Testhdr1"
23+
hdr["header2"] = "Testhdr2"
24+
// Multivalue query strings
25+
mvqs["k1"] = []string{"t1"}
26+
mvqs["k2"] = []string{"t2"}
27+
bdy := "Test BODY"
28+
basePathRequest := getFunctionUrlProxyRequest("/hello", getFunctionUrlRequestContext("/hello", "GET"), false, hdr, bdy, qs, mvqs)
29+
30+
It("Correctly converts a basic event", func() {
31+
httpReq, err := accessor.EventToRequestWithContext(context.Background(), basePathRequest)
32+
Expect(err).To(BeNil())
33+
Expect("/hello").To(Equal(httpReq.URL.Path))
34+
Expect("/hello?UniqueId=12345").To(Equal(httpReq.RequestURI))
35+
Expect("GET").To(Equal(httpReq.Method))
36+
headers := basePathRequest.Headers
37+
Expect(2).To(Equal(len(headers)))
38+
})
39+
40+
binaryBody := make([]byte, 256)
41+
_, err := rand.Read(binaryBody)
42+
if err != nil {
43+
Fail("Could not generate random binary body")
44+
}
45+
46+
encodedBody := base64.StdEncoding.EncodeToString(binaryBody)
47+
48+
binaryRequest := getFunctionUrlProxyRequest("/hello", getFunctionUrlRequestContext("/hello", "POST"), true, hdr, bdy, qs, mvqs)
49+
binaryRequest.Body = encodedBody
50+
binaryRequest.IsBase64Encoded = true
51+
52+
It("Decodes a base64 encoded body", func() {
53+
httpReq, err := accessor.EventToRequestWithContext(context.Background(), binaryRequest)
54+
Expect(err).To(BeNil())
55+
Expect("/hello").To(Equal(httpReq.URL.Path))
56+
Expect("/hello?UniqueId=12345").To(Equal(httpReq.RequestURI))
57+
Expect("POST").To(Equal(httpReq.Method))
58+
})
59+
60+
mqsRequest := getFunctionUrlProxyRequest("/hello", getFunctionUrlRequestContext("/hello", "GET"), false, hdr, bdy, qs, mvqs)
61+
mqsRequest.RawQueryString = "hello=1&world=2&world=3"
62+
mqsRequest.QueryStringParameters = map[string]string{
63+
"hello": "1",
64+
"world": "2",
65+
}
66+
67+
It("Populates query string correctly", func() {
68+
httpReq, err := accessor.EventToRequestWithContext(context.Background(), mqsRequest)
69+
Expect(err).To(BeNil())
70+
Expect("/hello").To(Equal(httpReq.URL.Path))
71+
fmt.Println("SDYFSDKFJDL")
72+
fmt.Printf("%v", httpReq.RequestURI)
73+
Expect(httpReq.RequestURI).To(ContainSubstring("hello=1"))
74+
Expect(httpReq.RequestURI).To(ContainSubstring("world=2"))
75+
Expect("GET").To(Equal(httpReq.Method))
76+
query := httpReq.URL.Query()
77+
Expect(2).To(Equal(len(query)))
78+
Expect(query["hello"]).ToNot(BeNil())
79+
Expect(query["world"]).ToNot(BeNil())
80+
})
81+
})
82+
83+
Context("StripBasePath tests", func() {
84+
accessor := core.RequestAccessorFu{}
85+
It("Adds prefix slash", func() {
86+
basePath := accessor.StripBasePath("app1")
87+
Expect("/app1").To(Equal(basePath))
88+
})
89+
90+
It("Removes trailing slash", func() {
91+
basePath := accessor.StripBasePath("/app1/")
92+
Expect("/app1").To(Equal(basePath))
93+
})
94+
95+
It("Ignores blank strings", func() {
96+
basePath := accessor.StripBasePath(" ")
97+
Expect("").To(Equal(basePath))
98+
})
99+
})
100+
})
101+
102+
func getFunctionUrlProxyRequest(path string, requestCtx events.LambdaFunctionURLRequestContext,
103+
is64 bool, header map[string]string, body string, qs map[string]string, mvqs map[string][]string) events.LambdaFunctionURLRequest {
104+
return events.LambdaFunctionURLRequest{
105+
RequestContext: requestCtx,
106+
RawPath: path,
107+
RawQueryString: generateQueryString(qs),
108+
Headers: header,
109+
Body: body,
110+
IsBase64Encoded: is64,
111+
}
112+
}
113+
114+
func getFunctionUrlRequestContext(path, method string) events.LambdaFunctionURLRequestContext {
115+
return events.LambdaFunctionURLRequestContext{
116+
DomainName: "example.com",
117+
HTTP: events.LambdaFunctionURLRequestContextHTTPDescription{
118+
Method: method,
119+
Path: path,
120+
},
121+
}
122+
}
123+
124+
func generateQueryString(queryParameters map[string]string) string {
125+
var queryString string
126+
for key, value := range queryParameters {
127+
if queryString != "" {
128+
queryString += "&"
129+
}
130+
queryString += fmt.Sprintf("%s=%s", key, value)
131+
}
132+
return queryString
133+
}

Diff for: core/requestv2_test.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package core_test
33
import (
44
"context"
55
"encoding/base64"
6-
"github.com/onsi/gomega/gstruct"
6+
"fmt"
77
"io/ioutil"
88
"math/rand"
99
"os"
1010
"strings"
1111

12+
"github.com/onsi/gomega/gstruct"
13+
1214
"github.com/aws/aws-lambda-go/events"
1315
"github.com/aws/aws-lambda-go/lambdacontext"
1416
"github.com/awslabs/aws-lambda-go-api-proxy/core"
@@ -74,6 +76,8 @@ var _ = Describe("RequestAccessorV2 tests", func() {
7476
It("Populates multiple value query string correctly", func() {
7577
httpReq, err := accessor.EventToRequestWithContext(context.Background(), mqsRequest)
7678
Expect(err).To(BeNil())
79+
fmt.Println("SDY!@$#!@FSDKFJDL")
80+
fmt.Printf("%v", httpReq.RequestURI)
7781
Expect("/hello").To(Equal(httpReq.URL.Path))
7882
Expect(httpReq.RequestURI).To(ContainSubstring("hello=1"))
7983
Expect(httpReq.RequestURI).To(ContainSubstring("world=2"))

Diff for: core/responseFunctionUrl_test.go

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package core
2+
3+
import (
4+
"math/rand"
5+
"net/http"
6+
"strings"
7+
8+
. "github.com/onsi/ginkgo"
9+
. "github.com/onsi/gomega"
10+
)
11+
12+
var _ = Describe("FunctionUrlResponseWriter tests", func() {
13+
Context("writing to response object", func() {
14+
response := NewFunctionUrlResponseWriter()
15+
16+
It("Sets the correct default status", func() {
17+
Expect(defaultStatusCode).To(Equal(response.status))
18+
})
19+
20+
It("Initializes the headers map", func() {
21+
Expect(response.headers).ToNot(BeNil())
22+
Expect(0).To(Equal(len(response.headers)))
23+
})
24+
25+
It("Writes headers correctly", func() {
26+
response.Header().Add("Content-Type", "application/json")
27+
28+
Expect(1).To(Equal(len(response.headers)))
29+
Expect("application/json").To(Equal(response.headers["Content-Type"][0]))
30+
})
31+
32+
It("Writes body content correctly", func() {
33+
binaryBody := make([]byte, 256)
34+
_, err := rand.Read(binaryBody)
35+
Expect(err).To(BeNil())
36+
37+
written, err := response.Write(binaryBody)
38+
Expect(err).To(BeNil())
39+
Expect(len(binaryBody)).To(Equal(written))
40+
})
41+
42+
It("Automatically set the status code to 200", func() {
43+
Expect(http.StatusOK).To(Equal(response.status))
44+
})
45+
46+
It("Forces the status to a new code", func() {
47+
response.WriteHeader(http.StatusAccepted)
48+
Expect(http.StatusAccepted).To(Equal(response.status))
49+
})
50+
})
51+
52+
Context("Automatically set response content type", func() {
53+
xmlBodyContent := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>"
54+
htmlBodyContent := " <!DOCTYPE html><html><head><meta charset=\"UTF-8\"><title>Title of the document</title></head><body>Content of the document......</body></html>"
55+
56+
It("Does not set the content type if it's already set", func() {
57+
resp := NewFunctionUrlResponseWriter()
58+
resp.Header().Add("Content-Type", "application/json")
59+
60+
resp.Write([]byte(xmlBodyContent))
61+
62+
Expect("application/json").To(Equal(resp.Header().Get("Content-Type")))
63+
proxyResp, err := resp.GetFunctionUrlResponse()
64+
Expect(err).To(BeNil())
65+
Expect(1).To(Equal(len(proxyResp.Headers)))
66+
Expect("application/json").To(Equal(proxyResp.Headers["Content-Type"]))
67+
Expect(xmlBodyContent).To(Equal(proxyResp.Body))
68+
})
69+
70+
It("Sets the content type to text/xml given the body", func() {
71+
resp := NewFunctionUrlResponseWriter()
72+
resp.Write([]byte(xmlBodyContent))
73+
74+
Expect("").ToNot(Equal(resp.Header().Get("Content-Type")))
75+
Expect(true).To(Equal(strings.HasPrefix(resp.Header().Get("Content-Type"), "text/xml;")))
76+
proxyResp, err := resp.GetFunctionUrlResponse()
77+
Expect(err).To(BeNil())
78+
Expect(1).To(Equal(len(proxyResp.Headers)))
79+
Expect(true).To(Equal(strings.HasPrefix(proxyResp.Headers["Content-Type"], "text/xml;")))
80+
Expect(xmlBodyContent).To(Equal(proxyResp.Body))
81+
})
82+
83+
It("Sets the content type to text/html given the body", func() {
84+
resp := NewFunctionUrlResponseWriter()
85+
resp.Write([]byte(htmlBodyContent))
86+
87+
Expect("").ToNot(Equal(resp.Header().Get("Content-Type")))
88+
Expect(true).To(Equal(strings.HasPrefix(resp.Header().Get("Content-Type"), "text/html;")))
89+
proxyResp, err := resp.GetFunctionUrlResponse()
90+
Expect(err).To(BeNil())
91+
Expect(1).To(Equal(len(proxyResp.Headers)))
92+
Expect(true).To(Equal(strings.HasPrefix(proxyResp.Headers["Content-Type"], "text/html;")))
93+
Expect(htmlBodyContent).To(Equal(proxyResp.Body))
94+
})
95+
})
96+
97+
Context("Export Lambda Function URL response", func() {
98+
emptyResponse := NewFunctionUrlResponseWriter()
99+
emptyResponse.Header().Add("Content-Type", "application/json")
100+
101+
It("Refuses empty responses with default status code", func() {
102+
_, err := emptyResponse.GetFunctionUrlResponse()
103+
Expect(err).ToNot(BeNil())
104+
Expect("Status code not set on response").To(Equal(err.Error()))
105+
})
106+
107+
simpleResponse := NewFunctionUrlResponseWriter()
108+
simpleResponse.Write([]byte("https://example.com"))
109+
simpleResponse.WriteHeader(http.StatusAccepted)
110+
111+
It("Writes function URL response correctly", func() {
112+
functionUrlResponse, err := simpleResponse.GetFunctionUrlResponse()
113+
Expect(err).To(BeNil())
114+
Expect(functionUrlResponse).ToNot(BeNil())
115+
Expect(http.StatusAccepted).To(Equal(functionUrlResponse.StatusCode))
116+
})
117+
})
118+
})

0 commit comments

Comments
 (0)