Skip to content

Instantly share code, notes, and snippets.

@shankarshastri
Forked from crypticmind/README.md
Created March 22, 2020 05:33
Show Gist options
  • Save shankarshastri/5bc0635739ac8381c4652602488f04b0 to your computer and use it in GitHub Desktop.
Save shankarshastri/5bc0635739ac8381c4652602488f04b0 to your computer and use it in GitHub Desktop.
Setup lambda + API Gateway using localstack

About

Example on how to run locally an AWS Lambda via API Gateway using localstack.

Based on...

  1. https://stackoverflow.com/questions/44547574/create-api-gateway-in-localstack/48682628
  2. https://ig.nore.me/2016/03/setting-up-lambda-and-a-gateway-through-the-cli/

Usage

  1. Build a zip containing lambda.js, name it api-handler.zip
  2. Launch localstack in whatever way you can. See sample docker-compose.yml.
  3. Run setup.sh

Pending

  1. Catch any URL /api/whatever.
  2. Pass all HTTP verbs. Only GET is configured here. Other verbs require their own integration as ANY is not supported yet.
  3. No query parameters yet.
version: '2.1'
services:
localstack:
image: localstack/localstack
ports:
- "4567-4583:4567-4583"
- "${PORT_WEB_UI-4566}:${PORT_WEB_UI-8080}"
environment:
- SERVICES=${SERVICES-lambda,apigateway }
- DEBUG=${DEBUG- }
- DATA_DIR=${DATA_DIR- }
- PORT_WEB_UI=${PORT_WEB_UI- }
- LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR-docker-reuse }
- KINESIS_ERROR_PROBABILITY=${KINESIS_ERROR_PROBABILITY- }
- DOCKER_HOST=unix:///var/run/docker.sock
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
'use strict'
const apiHandler = (payload, context, callback) => {
console.log(`Function apiHandler called with payload ${JSON.stringify(payload)}`);
callback(null, {
statusCode: 201,
body: JSON.stringify({
message: 'Hello World'
}),
headers: {
'X-Custom-Header': 'ASDF'
}
});
}
module.exports = {
apiHandler,
}
#!/bin/sh
API_NAME=api
REGION=us-east-1
STAGE=test
function fail() {
echo $2
exit $1
}
awslocal lambda create-function \
--region ${REGION} \
--function-name ${API_NAME} \
--runtime nodejs8.10 \
--handler lambda.apiHandler \
--memory-size 128 \
--zip-file fileb://api-handler.zip \
--role arn:aws:iam::123456:role/irrelevant
[ $? == 0 ] || fail 1 "Failed: AWS / lambda / create-function"
LAMBDA_ARN=$(awslocal lambda list-functions --query "Functions[?FunctionName==\`${API_NAME}\`].FunctionArn" --output text --region ${REGION})
awslocal apigateway create-rest-api \
--region ${REGION} \
--name ${API_NAME}
[ $? == 0 ] || fail 2 "Failed: AWS / apigateway / create-rest-api"
API_ID=$(awslocal apigateway get-rest-apis --query "items[?name==\`${API_NAME}\`].id" --output text --region ${REGION})
PARENT_RESOURCE_ID=$(awslocal apigateway get-resources --rest-api-id ${API_ID} --query 'items[?path==`/`].id' --output text --region ${REGION})
awslocal apigateway create-resource \
--region ${REGION} \
--rest-api-id ${API_ID} \
--parent-id ${PARENT_RESOURCE_ID} \
--path-part "{somethingId}"
[ $? == 0 ] || fail 3 "Failed: AWS / apigateway / create-resource"
RESOURCE_ID=$(awslocal apigateway get-resources --rest-api-id ${API_ID} --query 'items[?path==`/{somethingId}`].id' --output text --region ${REGION})
awslocal apigateway put-method \
--region ${REGION} \
--rest-api-id ${API_ID} \
--resource-id ${RESOURCE_ID} \
--http-method GET \
--request-parameters "method.request.path.somethingId=true" \
--authorization-type "NONE" \
[ $? == 0 ] || fail 4 "Failed: AWS / apigateway / put-method"
awslocal apigateway put-integration \
--region ${REGION} \
--rest-api-id ${API_ID} \
--resource-id ${RESOURCE_ID} \
--http-method GET \
--type AWS_PROXY \
--integration-http-method POST \
--uri arn:aws:apigateway:${REGION}:lambda:path/2015-03-31/functions/${LAMBDA_ARN}/invocations \
--passthrough-behavior WHEN_NO_MATCH \
[ $? == 0 ] || fail 5 "Failed: AWS / apigateway / put-integration"
awslocal apigateway create-deployment \
--region ${REGION} \
--rest-api-id ${API_ID} \
--stage-name ${STAGE} \
[ $? == 0 ] || fail 6 "Failed: AWS / apigateway / create-deployment"
ENDPOINT=http://localhost:4567/restapis/${API_ID}/${STAGE}/_user_request_/HowMuchIsTheFish
echo "API available at: ${ENDPOINT}"
echo "Testing GET:"
curl -i ${ENDPOINT}
echo "Testing POST:"
curl -iX POST ${ENDPOINT}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment