Skip to content

Instantly share code, notes, and snippets.

@crypticmind
Last active March 18, 2025 16:24
Show Gist options
  • Save crypticmind/c75db15fd774fe8f53282c3ccbe3d7ad to your computer and use it in GitHub Desktop.
Save crypticmind/c75db15fd774fe8f53282c3ccbe3d7ad 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}
@vak-rashu
Copy link

It is not working, either internal server error or authentication error is coming

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment