Skip to content

Commit

Permalink
Add events for lambda ALB integration (#149)
Browse files Browse the repository at this point in the history
Adding events for Lambda ALB integration
  • Loading branch information
sjurtf authored and furiousbunny committed Dec 17, 2018
1 parent 554303c commit 1be8070
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 0 deletions.
38 changes: 38 additions & 0 deletions events/README_ALBTargetGroupEvents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Overview

ALB Target Group events consist of a request that was routed to a Lambda function which is a registered target of an Application Load Balancer Target Group. When this happens, ALB expects the result of the function to be the response that ALB should respond with.

https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html

# Sample Function

The following is a sample class and Lambda function that receives an ALB Target Group event as an input, writes some of the incoming data to CloudWatch Logs, and responds with a 200 status and the same body as the request. (Note that by default anything written to Console will be logged as CloudWatch Logs events.)

```go

package main

import (
"context"
"fmt"

"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)

func handleRequest(ctx context.Context, request events.ALBTargetGroupRequest) (events.ALBTargetGroupResponse, error) {
fmt.Printf("Processing request data for traceId %s.\n", request.Headers["x-amzn-trace-id"])
fmt.Printf("Body size = %d.\n", len(request.Body))

fmt.Println("Headers:")
for key, value := range request.Headers {
fmt.Printf(" %s: %s\n", key, value)
}

return events.ALBTargetGroupResponse{Body: request.Body, StatusCode: 200, StatusDescription: "200 OK", IsBase64Encoded: false}, nil
}

func main() {
lambda.Start(handleRequest)
}
```
34 changes: 34 additions & 0 deletions events/alb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package events

// ALBTargetGroupRequest contains data originating from the ALB Lambda target group integration
type ALBTargetGroupRequest struct {
HTTPMethod string `json:"httpMethod"`
Path string `json:"path"`
QueryStringParameters map[string]string `json:"queryStringParameters"`
MultiValueQueryStringParameters map[string][]string `json:"multiValueQueryStringParameters"`
Headers map[string]string `json:"headers"`
MultiValueHeaders map[string][]string `json:"multiValueHeaders"`
RequestContext ALBTargetGroupRequestContext `json:"requestContext"`
IsBase64Encoded bool `json:"isBase64Encoded"`
Body string `json:"body"`
}

// ALBTargetGroupRequestContext contains the information to identify the load balancer invoking the lambda
type ALBTargetGroupRequestContext struct {
ELB ELBContext `json:"elb"`
}

// ELBContext contains the information to identify the ARN invoking the lambda
type ELBContext struct {
TargetGroupArn string `json:"targetGroupArn"`
}

// ALBTargetGroupResponse configures the response to be returned by the ALB Lambda target group for the request
type ALBTargetGroupResponse struct {
StatusCode int `json:"statusCode"`
StatusDescription string `json:"statusDescription"`
Headers map[string]string `json:"headers"`
MultiValueHeaders map[string][]string `json:"multiValueHeaders"`
Body string `json:"body"`
IsBase64Encoded bool `json:"isBase64Encoded"`
}
59 changes: 59 additions & 0 deletions events/alb_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package events

import (
"encoding/json"
"io/ioutil"
"testing"

"github.com/aws/aws-lambda-go/events/test"
"github.com/stretchr/testify/assert"
)

func TestALBTargetRequestMarshaling(t *testing.T) {
// read json from file
inputJSON, err := ioutil.ReadFile("./testdata/alb-lambda-target-request.json")
if err != nil {
t.Errorf("could not open test file. details: %v", err)
}

// de-serialize into Go object
var inputEvent ALBTargetGroupRequest
if err := json.Unmarshal(inputJSON, &inputEvent); err != nil {
t.Errorf("could not unmarshal event. details: %v", err)
}

// serialize to json
outputJSON, err := json.Marshal(inputEvent)
if err != nil {
t.Errorf("could not marshal event. details: %v", err)
}

assert.JSONEq(t, string(inputJSON), string(outputJSON))
}

func TestALBTargetRequestMalformedJson(t *testing.T) {
test.TestMalformedJson(t, ALBTargetGroupRequest{})
}

func TestALBTargetResponseMarshaling(t *testing.T) {

// read json from file
inputJSON, err := ioutil.ReadFile("./testdata/alb-lambda-target-response.json")
if err != nil {
t.Errorf("could not open test file. details: %v", err)
}

// de-serialize into Go object
var inputEvent ALBTargetGroupResponse
if err := json.Unmarshal(inputJSON, &inputEvent); err != nil {
t.Errorf("could not unmarshal event. details: %v", err)
}

// serialize to json
outputJSON, err := json.Marshal(inputEvent)
if err != nil {
t.Errorf("could not marshal event. details: %v", err)
}

assert.JSONEq(t, string(inputJSON), string(outputJSON))
}
50 changes: 50 additions & 0 deletions events/testdata/alb-lambda-target-request.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"requestContext": {
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:region:123456789012:targetgroup/my-target-group/6d0ecf831eec9f09"
}
},
"httpMethod": "GET",
"path": "/",
"queryStringParameters": {
"testparam": "true"
},
"multiValueQueryStringParameters": {
"name": ["me"]
},
"headers": {
"accept": "text/html,application/xhtml+xml",
"accept-language": "en-US,en;q=0.8",
"content-type": "text/plain",
"cookie": "cookies",
"host": "lambda-846800462-us-east-2.elb.amazonaws.com",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6)",
"x-amzn-trace-id": "Root=1-5bdb40ca-556d8b0c50dc66f0511bf520",
"x-forwarded-for": "72.21.198.66",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
},
"multiValueHeaders": {
"Accept": ["*/*"],
"Accept-Encoding": ["gzip, deflate"],
"cache-control": ["no-cache"],
"CloudFront-Forwarded-Proto": ["https"],
"CloudFront-Is-Desktop-Viewer": ["true"],
"CloudFront-Is-Mobile-Viewer": ["false"],
"CloudFront-Is-SmartTV-Viewer": ["false"],
"CloudFront-Is-Tablet-Viewer": ["false"],
"CloudFront-Viewer-Country": ["US"],
"Content-Type": ["application/json"],
"headerName": ["headerValue"],
"Host": ["gy415nuibc.execute-api.us-east-1.amazonaws.com"],
"Postman-Token": ["9f583ef0-ed83-4a38-aef3-eb9ce3f7a57f"],
"User-Agent": ["PostmanRuntime/2.4.5"],
"Via": ["1.1 d98420743a69852491bbdea73f7680bd.cloudfront.net (CloudFront)"],
"X-Amz-Cf-Id": ["pn-PWIJc6thYnZm5P0NMgOUglL1DYtl0gdeJky8tqsg8iS_sgsKD1A=="],
"X-Forwarded-For": ["54.240.196.186, 54.182.214.83"],
"X-Forwarded-Port": ["443"],
"X-Forwarded-Proto": ["https"]
},
"isBase64Encoded": false,
"body": "Who there?"
}
14 changes: 14 additions & 0 deletions events/testdata/alb-lambda-target-response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"isBase64Encoded": false,
"statusCode": 200,
"statusDescription": "200 OK",
"headers": {
"Set-cookie": "cookies",
"Content-Type": "application/json"
},
"multiValueHeaders": {
"Set-cookie": ["cookie-name=cookie-value;Domain=myweb.com;Secure;HttpOnly","cookie-name=cookie-value;Expires=May 8, 2019"],
"Content-Type": ["application/json"]
},
"body": "Hello from Lambda"
}

0 comments on commit 1be8070

Please sign in to comment.