Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create API gateway in localstack

I was able to setup localstack (https://github.com/atlassian/localstack) and also create lambda function in it (using create-function ... command). However, I couldnt find a way to create an APIGateway in localstack so that the lambda function can be called using it. Basically, I need an APIGateway(and its arn), so that using that the lambda function can be called.

like image 605
nodejs1 Avatar asked Jun 14 '17 14:06

nodejs1


People also ask

Does serverless framework create API Gateway?

By default, Serverless creates automatically an API Gateway for each Serverless stack or service (i.e. serverless. yml ) you deploy.

Can I use API Gateway with EC2?

You can create an API Gateway API with private integration to provide your customers access to HTTP/HTTPS resources within your Amazon Virtual Private Cloud (Amazon VPC). Such VPC resources are HTTP/HTTPS endpoints on an EC2 instance behind a Network Load Balancer in the VPC.


1 Answers

Walkthrough for creating a NodeJS Lambda together with API Gateway per CLI:

First we create a simple NodeJS Lambda:

const apiTestHandler = (payload, context, callback) => {
console.log(`Function apiTestHandler called with payload ${JSON.stringify(payload)}`);
callback(null, {
    statusCode: 201,
    body: JSON.stringify({
        somethingId: payload.pathParameters.somethingId
    }),
    headers: {
        "X-Click-Header": "abc"
    }
}); 
}
module.exports = {
    apiTestHandler,
}

Put that into a zip File called apiTestHandler.zip and upload it to localstack:

aws lambda create-function \
--region us-east-1 \
--function-name api-test-handler \
--runtime nodejs6.10 \
--handler index.apiTestHandler \
--memory-size 128 \
--zip-file fileb://apiTestHandler.zip \
--role arn:aws:iam::123456:role/role-name --endpoint-url=http://localhost:4574

Now we can create our Rest-Api:

aws apigateway create-rest-api --region us-east-1 --name 'API Test' --endpoint-url=http://localhost:4567

This gives the following response:

{
"name": "API Test",
"id": "487109A-Z548",
"createdDate": 1518081479
}

With the ID we got here, we can ask for its parent-ID:

aws apigateway get-resources --region us-east-1 --rest-api-id 487109A-Z548 --endpoint-url=http://localhost:4567

Response:

{
"items": [
    {
        "path": "/",
        "id": "0270A-Z23550",
        "resourceMethods": {
            "GET": {}
        }
    }
]
}

Now we have everything to create our resource together with its path:

aws apigateway create-resource \
--region us-east-1 \
--rest-api-id 487109A-Z548 \
--parent-id 0270A-Z23550 \
--path-part "{somethingId}" --endpoint-url=http://localhost:4567

Response:

{
"resourceMethods": {
    "GET": {}
},
"pathPart": "{somethingId}",
"parentId": "0270A-Z23550",
"path": "/{somethingId}",
"id": "0662807180"
}

The ID we got here is needed to create our linked GET Method:

aws apigateway put-method \
 --region us-east-1 \
 --rest-api-id 487109A-Z548 \
 --resource-id 0662807180 \
 --http-method GET \
 --request-parameters "method.request.path.somethingId=true" \
 --authorization-type "NONE" \
--endpoint-url=http://localhost:4567

We are almost there - one of the last things to do is to create our integration with the already uploaded lambda:

aws apigateway put-integration \
 --region us-east-1 \
 --rest-api-id 487109A-Z548 \
 --resource-id 0662807180 \
 --http-method GET \
 --type AWS_PROXY \
 --integration-http-method POST \
 --uri arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:api-test-handler/invocations \
 --passthrough-behavior WHEN_NO_MATCH \
 --endpoint-url=http://localhost:4567

Last but not least: Deploy our API to our desired stage:

aws apigateway create-deployment \
 --region us-east-1 \
 --rest-api-id 487109A-Z548 \
 --stage-name test \
 --endpoint-url=http://localhost:4567

Now we can test it:

curl http://localhost:4567/restapis/487109A-Z548/test/_user_request_/HowMuchIsTheFish

Response:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                             Dload  Upload   Total   Spent    Left  Speed
100    34  100    34    0     0      9      0  0:00:03  0:00:03 --:--:--     9
{"somethingId":"HowMuchIsTheFish"}

I hope this helps.

Hint 1: For easier use I recommend to install AWSCLI Local ( https://github.com/localstack/awscli-local ) - with this tool you can use the command "awslocal" and don't have to type "--endpoint-url= ..." for each command

Walkthrough for using Serverless Framework and Localstack:

You can also use the Serverless Framework (https://serverless.com/).

First install it via npm:

npm install serverless -g

Now you can create a sample application based on a nodejs-aws template:

serverless create --template aws-nodejs

In order to have an HTTP endpoint, you have to edit the serverless.yml and add the corresponding event :

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: ping
          method: get

In order to run this against your localstack installation you have to use the serverless-localstack plugin ( https://github.com/temyers/serverless-localstack):

npm install serverless-localstack

Now you have to edit your serverless.yml again, add the plugin and adjust your endpoints. In my case localstack is running inside the Docker toolbox, so it's IP is 192.168.99.100 - you may have to change this to localhost, depending on your use:

plugins:
 - serverless-localstack
custom:
  localstack:
    debug: true
    stages:
      - local
      - dev
    host: http://192.168.99.100
    endpoints:
      S3: http://192.168.99.100:4572
      DynamoDB: http://192.168.99.100:4570
      CloudFormation: http://192.168.99.100:4581
      Elasticsearch: http://192.168.99.100:4571
      ES: http://192.168.99.100:4578
      SNS: http://192.168.99.100:4575
      SQS: http://192.168.99.100:4576
      Lambda: http://192.168.99.100:4574
      Kinesis: http://192.168.99.100:4568

Now you can try to deploy it:

serverless deploy --verbose --stage local

This will create an S3 bucket, upload your lambda and create a cloudformation stack. However, the process will fail due to some inconsistencies of localstack when compared against AWS. Don't be dismayed though, the created cloudformation template works fine and you just need an additional request and you are done:

awslocal cloudformation update-stack --template-body file://.serverless/cloudformation-template-update-stack.json --stack-name aws-nodejs-local

Now your lambda is deployed and can be tested:

curl http://192.168.99.100:4567/restapis/75A-Z278430A-Z/local/_user_request_/ping

Response:

% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current Dload  Upload   Total   Spent    Left  Speed
100   364  100   364    0     0    111      0  0:00:03  0:00:03 --:--:--   111
{"message":"Go Serverless v1.0! Your function executed successfully!","input":{"body":null,"headers":{"host":"192.168.99.100:4567","accept":"*/*","user-agent":"curl/7.49.1"},"resource":"/restapis/75A-Z278430A-Z/local/_user_request_/ping","queryStringParameters":{},"httpMethod":"GET","stageVariables":{},"path":"/ping","pathParameters":{},"isBase64Encoded":false}}

Hope this helps.

like image 56
Steffen Bach Avatar answered Oct 16 '22 21:10

Steffen Bach