-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add support for api gateway v2 requests and responses. update to g 1.…
…21 for slog adapter
- Loading branch information
1 parent
27a1d5b
commit 4525257
Showing
13 changed files
with
398 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package shim | ||
|
||
import ( | ||
"context" | ||
"encoding/base64" | ||
"fmt" | ||
"net/http" | ||
"net/url" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/aws/aws-lambda-go/events" | ||
) | ||
|
||
// NewHttpRequestFromAPIGatewayV2HTTPRequest creates an *http.Request from the context passed from the Lambda library, and the event itself. | ||
func NewHttpRequestFromAPIGatewayV2HTTPRequest(ctx context.Context, event events.APIGatewayV2HTTPRequest) (*http.Request, error) { | ||
u, err := url.Parse(event.RawPath) | ||
if err != nil { | ||
return nil, fmt.Errorf("shim could not parse path from event: %w", err) | ||
} | ||
|
||
if event.RawQueryString != "" { | ||
u.RawQuery = event.RawQueryString | ||
} | ||
|
||
body := event.Body | ||
if event.IsBase64Encoded { | ||
d, err := base64.StdEncoding.DecodeString(body) | ||
if err != nil { | ||
return nil, fmt.Errorf("shim encountered an error while base64 decoding request body: %w", err) | ||
} | ||
|
||
body = string(d) | ||
} | ||
|
||
req, err := http.NewRequest( | ||
event.RequestContext.HTTP.Method, | ||
u.String(), | ||
strings.NewReader(body), | ||
) | ||
|
||
if err != nil { | ||
return nil, fmt.Errorf("shim could not create http request from event: %w", err) | ||
} | ||
|
||
for h, v := range event.Headers { | ||
req.Header.Set(h, v) | ||
} | ||
|
||
req.URL.Host = req.Header.Get("Host") | ||
req.Host = req.Header.Get("Host") | ||
|
||
req.RemoteAddr = event.RequestContext.HTTP.SourceIP | ||
|
||
if req.Header.Get(contentLength) == "" && body != "" { | ||
req.Header.Set(contentLength, strconv.Itoa(len(body))) | ||
} | ||
|
||
req = req.WithContext(ctx) | ||
|
||
return req, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package shim | ||
|
||
import ( | ||
"context" | ||
"encoding/base64" | ||
"io/ioutil" | ||
"net/http" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/aws/aws-lambda-go/events" | ||
) | ||
|
||
func TestNewHttpRequestFromAPIGatewayV2HTTPRequest(t *testing.T) { | ||
ctx := context.Background() | ||
|
||
// Create a sample APIGatewayV2HTTPRequest event | ||
event := events.APIGatewayV2HTTPRequest{ | ||
Version: "2.0", | ||
RouteKey: "GET /hello", | ||
RawPath: "/hello", | ||
RawQueryString: "name=John&age=30", | ||
Headers: map[string]string{"Content-Type": "application/json"}, | ||
QueryStringParameters: map[string]string{"name": "John", "age": "30"}, | ||
} | ||
|
||
// Call the function under test | ||
req, err := NewHttpRequestFromAPIGatewayV2HTTPRequest(ctx, event) | ||
if err != nil { | ||
t.Errorf("unexpected error: %v", err) | ||
} | ||
|
||
// Verify the created request | ||
if req.Method != http.MethodGet { | ||
t.Errorf("expected GET method, got %s", req.Method) | ||
} | ||
|
||
if req.URL.Path != "/hello" { | ||
t.Errorf("expected path '/hello', got %s", req.URL.Path) | ||
} | ||
|
||
if req.URL.RawQuery != "name=John&age=30" { | ||
t.Errorf("expected query string 'name=John&age=30', got %s", req.URL.RawQuery) | ||
} | ||
|
||
if req.Header.Get("Content-Type") != "application/json" { | ||
t.Errorf("expected 'Content-Type' header to be 'application/json', got %s", req.Header.Get("Content-Type")) | ||
} | ||
|
||
if req.Context() != ctx { | ||
t.Error("expected context to be the same") | ||
} | ||
} | ||
|
||
func TestNewHttpRequestFromAPIGatewayV2HTTPRequest_Base64(t *testing.T) { | ||
ctx := context.Background() | ||
|
||
// Create a sample APIGatewayV2HTTPRequest event with base64 encoded body | ||
body := "Hello, World!" | ||
encodedBody := base64.StdEncoding.EncodeToString([]byte(body)) | ||
event := events.APIGatewayV2HTTPRequest{ | ||
Version: "2.0", | ||
RouteKey: "GET /hello", | ||
RawPath: "/hello", | ||
RawQueryString: "name=John&age=30", | ||
Headers: map[string]string{"Content-Type": "application/json"}, | ||
QueryStringParameters: map[string]string{"name": "John", "age": "30"}, | ||
Body: encodedBody, | ||
IsBase64Encoded: true, | ||
} | ||
|
||
// Call the function under test | ||
req, err := NewHttpRequestFromAPIGatewayV2HTTPRequest(ctx, event) | ||
if err != nil { | ||
t.Errorf("unexpected error: %v", err) | ||
} | ||
|
||
// Verify the created request | ||
decodedBody, err := ioutil.ReadAll(req.Body) | ||
if err != nil { | ||
t.Errorf("unexpected error when reading request body: %v", err) | ||
} | ||
|
||
if strings.TrimSpace(string(decodedBody)) != body { | ||
t.Errorf("expected body '%s', got '%s'", body, string(decodedBody)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package shim | ||
|
||
import ( | ||
"encoding/base64" | ||
"net/http" | ||
|
||
"github.com/aws/aws-lambda-go/events" | ||
) | ||
|
||
func NewApiGatewayV2HttpResponse(rw *ResponseWriter) events.APIGatewayV2HTTPResponse { | ||
resp := events.APIGatewayV2HTTPResponse{ | ||
StatusCode: rw.Code, | ||
} | ||
|
||
headers := rw.Headers | ||
headers[httpHeaderContentType] = []string{http.DetectContentType(rw.Body.Bytes())} | ||
|
||
resp.MultiValueHeaders = headers | ||
|
||
if shouldConvertToBase64(rw.Headers.Get(httpHeaderContentType)) { | ||
resp.Body = base64.StdEncoding.EncodeToString(rw.Body.Bytes()) | ||
resp.IsBase64Encoded = true | ||
} else { | ||
resp.Body = string(rw.Body.String()) | ||
} | ||
|
||
return resp | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package shim | ||
|
||
import ( | ||
"bytes" | ||
"compress/gzip" | ||
"encoding/base64" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"testing" | ||
) | ||
|
||
func TestNewApiGatewayV2HttpResponse_Base64(t *testing.T) { | ||
body, err := gzipString("hello, world") | ||
if err != nil { | ||
t.Fatalf("unable to gzip string: %v", err) | ||
} | ||
|
||
rw := NewResponseWriter() | ||
rw.Write([]byte(body)) | ||
rw.Headers.Set(httpHeaderContentType, "application/octet-stream") | ||
resp := NewApiGatewayV2HttpResponse(rw) | ||
|
||
if resp.StatusCode != rw.Code { | ||
t.Errorf("expected status code %d, got %d", rw.Code, resp.StatusCode) | ||
} | ||
|
||
if resp.Body != base64.StdEncoding.EncodeToString(rw.Body.Bytes()) { | ||
t.Errorf("expected body to be base64 encoded") | ||
} | ||
|
||
if !resp.IsBase64Encoded { | ||
t.Errorf("expected IsBase64Encoded to be true") | ||
} | ||
} | ||
|
||
func TestNewApiGatewayV2HttpResponse_NoBase64(t *testing.T) { | ||
rw := &ResponseWriter{ | ||
Code: http.StatusOK, | ||
Headers: http.Header{}, | ||
Body: *bytes.NewBufferString("Hello, World!"), | ||
} | ||
rw.Headers.Set(httpHeaderContentType, "text/plain") | ||
|
||
resp := NewApiGatewayV2HttpResponse(rw) | ||
|
||
if resp.StatusCode != rw.Code { | ||
t.Errorf("expected status code %d, got %d", rw.Code, resp.StatusCode) | ||
} | ||
|
||
if resp.Body != rw.Body.String() { | ||
t.Errorf("expected body to be '%s', got '%s'", rw.Body.String(), resp.Body) | ||
} | ||
|
||
if resp.IsBase64Encoded { | ||
t.Errorf("expected IsBase64Encoded to be false") | ||
} | ||
} | ||
|
||
func gzipString(input string) ([]byte, error) { | ||
var buf bytes.Buffer | ||
gz := gzip.NewWriter(&buf) | ||
|
||
if _, err := gz.Write([]byte(input)); err != nil { | ||
return nil, fmt.Errorf("unable to write to gzip writer: %w", err) | ||
} | ||
|
||
if err := gz.Close(); err != nil { | ||
return nil, fmt.Errorf("unable to close gzip writer: %w", err) | ||
} | ||
|
||
return buf.Bytes(), nil | ||
} | ||
|
||
func gunzipBytes(input []byte) (string, error) { | ||
buf := bytes.NewBuffer(input) | ||
gz, err := gzip.NewReader(buf) | ||
if err != nil { | ||
return "", fmt.Errorf("unable to create gzip reader: %w", err) | ||
} | ||
defer gz.Close() | ||
|
||
res, err := io.ReadAll(gz) | ||
if err != nil { | ||
return "", fmt.Errorf("unable to read from gzip reader: %w", err) | ||
} | ||
|
||
return string(res), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
module github.com/iamatypeofwalrus/shim | ||
|
||
go 1.17 | ||
go 1.21 | ||
|
||
require github.com/aws/aws-lambda-go v1.46.0 |
Oops, something went wrong.