That Lambda Proxy - Allows you to proxy AWS Lambda Function similar to AWS ELB or AWS API Gateway
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Darshil Chanpura 5e760d5f8c Minor testcase fix 11 months ago
cmd/that-lambda-proxy Added logic for disable-metrics and updated doc 11 months ago
etc/systemd/system Added value to host and port in service file. Fixes #2 1 year ago
lambdaproxy Added logic for disable-metrics and updated doc 11 months ago
server Minor testcase fix 11 months ago
.drone.yml Added ldflags for smaller binaries 11 months ago
.gitignore Added common pattern for flag and minor changes 11 months ago
LICENSE CI changes with service file and license 1 year ago
README.md Added logic for disable-metrics and updated doc 11 months ago
go.mod Added prometheus handler with vectors 11 months ago
go.sum Minor testcase fix 11 months ago

README.md

That Lambda Proxy

Build Status

For compute access and to avoid setting up an AWS EC2 instance we use AWS Lambda. For example, logging in and getting a token, CRUD operations, etc.

Usually in this case, basic approach is to use AWS Application Load Balancer or AWS API Gateway to access AWS Lambda. But they all have some limitations in terms of input payload limits and response limits and timeouts. There are some ways to configure it but there is a hard limit after which we cannot change.

To have ability to change configuration whenever needed, we use that-lambda-proxy which helps us achieve similar behavior as we would have observed in AWS ALB or AWS API Gateway.

How it works

When we start this app up it listens on a address (default 127.0.0.1:8011) and it expects a HTTP request on it with a header which provides which Lambda function to invoke. Internally when the server is hit with HTTP request it converts to a Lambda trigger event JSON payload.

To invoke lambda we need AWS configured in the system/instance. By default it looks into ~/.aws folder for credentials and configuration. If you're using AWS IAM Role attached to Instance the credentials are used from Instance Profile, as the code uses AWS SDK for calling the AWS APIs. In case if you want to override, following environment variables can be set.

export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=
export AWS_DEFAULT_REGION=us-east-1

Lambda Trigger Event - Request

The format is similar to ALB’s format as follows:

{
    "httpMethod": "POST",
    "path": "/add",
    "queryStringParameters": {
        "test": "true"
    },
    "headers": {
        "accept-encoding": "gzip",
        "accept-language": "en-US,en;q=0.9",
        "connection": "keep-alive",
        "content-type": "application/json",
        "host": "api.thatwebsite.xyz",
        "upgrade-insecure-requests": "1",
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
        "x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476",
        "x-forwarded-for": "1.2.3.4",
        "x-forwarded-port": "443",
        "x-forwarded-proto": "https",
        "x-imforwards": "20"
    },
    "body": "{\"test\":1}",
    "isBase64Encoded": false
}

The main keys here are:

  • httpMethod: HTTP Method
  • path: Path like /add if the request URL is https://api.thatwebsite.xyz/add?test=true
  • queryStringParameters: JSON Object with key and value from the query parameters. e.g. {"test": "true"}
  • headers: JSON Object with key as header and value as header’s first value.
  • body: Body in string
  • isBase64Encoded: Should be true if body is base64 encoded.

Lambda Output - Response

In response also we cannot just get body and send it back as response from proxy, so we have similar structure from Lambda to create a HTTP Response.

{
    "statusCode": 200,
    "isBase64Encoded": false,
    "headers": {
        "Content-Type": "application/json"
    },
    "body": "{\"ok\":true}"
}

Again main keys are:

  • statusCode: HTTP Response code
  • isBase64Encoded: True if body is base64 encoded
  • headers: JSON Object having key value pairs of response headers
  • body: Response body

Installation

That Lambda Proxy comes with a binary specific to architecture and operating system. Currently there are no packages available, but the installation is simply copying this binary to /usr/local/bin and it should work just fine.

tar -xvf that-lambda-proxy-amd64-linux.tar.gz

The package also includes a Systemd Service file for the same which allows you to install it as service.

sudo cp that-lambda-proxy /usr/local/bin
sudo cp that-lambda-proxy.service /etc/systemd/system/
sudo systemctl start that-lambda-proxy.service
sudo systemctl enable that-lambda-proxy.service # To start service with instance startup

In case if you want the proxy to run on a different port, just add a parameter in service file where we have the ExecStart as -port 8012 which will start the service on port 8012. Whenever there’s a change in service file try to run systemctl daemon-reload once with root so that it reloads the configuration.

Nginx configuration

Simple configuration can be by just adding proxy_set_header X-Lambda-Function line as mentioned below.

server {
  server_name api.thatwebsite.xyz;
  ...
  location / {
    ...
    # proxy_pass http://that-elb-hostname; # ALB
    proxy_pass http://127.0.0.1:8011; # Extra

    proxy_set_header X-Lambda-Function thatwebsite-api-function; # Extra
    proxy_set_header Host $proxy_host;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;
    ...
  }
}

In case if your app expects another path like /api/ we can do that change in proxy_pass and add path after the URL.

server {
  location / {
    ...
    proxy_pass http://127.0.0.1:8011/api/;
    ...
  }
}

Logging

The service by default logs in Journal log. In case if you’re running it directly from command line it will log it to Standard Output.

Usage

that-lambda-proxy can be ran as a service as mentioned in installation section. Command still accepts some parameters as follows.

  • host: Host to listen on, by default 127.0.0.1.
  • port: Port to listen on, by default 8011.
  • disable-metrics: Disables the prometheus metrics on /metrics.
  • aws-region: AWS Region to use for calling AWS APIs default is AWS_DEFAULT_REGION (if empty, us-east-1).
  • aws-profile: AWS Profile in case of using different profile from ~/.aws/credentials.
$ that-lambda-proxy -h
Usage of that-lambda-proxy:
  -aws-profile string
        Profile to use (default "default")
  -aws-region string
        Region to use (default "us-east-1")
  -disable-metrics
        Disables metrics on /metrics path
  -host string
        Host to listen the server on (default "127.0.0.1")
  -port int
        Port to listen the server on (default 8011)

License

MIT