Note: I've re-deployed to a new region, so I've manually modified the new End points, so the Picture in the URL is different, but its the same output.
For this tutorial we are going to use the serverless application framework for NodeJS.
First lets install the serverless package.
root@damrkul2:~/# npm install -g serverless --ignore-scripts spawn-sync /usr/bin/serverless -> /usr/lib/node_modules/serverless/bin/serverless /usr/bin/slss -> /usr/lib/node_modules/serverless/bin/serverless /usr/bin/sls -> /usr/lib/node_modules/serverless/bin/serverless + serverless@1.30.1 + spawn-sync@2.0.0 added 1 package from 1 contributor and updated 1 package in 8.441s
Once that's been installed, lets create directory, and enter it, and then run the following command. You must specify a template or you will get an error message.
Here is a list of templates we can use for Various languages:
For this tutorial we will be using aws-nodejs... but whats cool about this package is we can use another language if needed!
So lets run the command.
root@damrkul2:~/lambda_example# serverless create --template aws-nodejs Serverless: Generating boilerplate... _______ __ | _ .-----.----.--.--.-----.----| .-----.-----.-----. | |___| -__| _| | | -__| _| | -__|__ --|__ --| |____ |_____|__| \___/|_____|__| |__|_____|_____|_____| | | | The Serverless Application Framework | | serverless.com, v1.30.1 -------' Serverless: Successfully generated boilerplate for template: "aws-nodejs" Serverless: NOTE: Please update the "service" property in serverless.yml with your service name
After executing that command we are left with 2 files in the directory. A handler.js and serverless.yaml file.
serverless.yaml
This is a yaml file that is used to configure the function. For example, we can configure its access privledges, such as assigning IAM roles. This would also be the place where we could define triggers for when the function can be called. For example, we could have this function be triggered when a file is uploaded to the S3 Bucket. The template that is provided comes with alot of commented action examples that you could find useful in the future.
For this tutorial though, we are going to keep it pretty simple.
First, lets rename our serverless application to something useful. Lets modify the value of the to "service: rekous-lambda-test" , which becomes the name of our serverless application.
We will also add an event HTTP event GET request for our function, along with a path for our endpoint. If this doesnt make sense now, it will in a few minutes. Anyways, I've removed all of the comments from the template, to clean up the file and show you all that is needed for right now.
# # Rekous First Lambda Function # service: rekous-lambda-test provider: name: aws runtime: nodejs8.10 functions: hello: handler: handler.hello events: - http: path: output/ method: get
So you can see, in the functions: , we define out "hello" function. Inside of the function we specify the actual handler to be used. And then our events, we are using http , with path and method parameters for that event.
handler.js
'use strict'; module.exports.hello = async (event, context) => { return { statusCode: 200, body: JSON.stringify({ message: 'Go Serverless v1.0! Your function executed successfully!', input: event, }), }; // Use this code if you don't use the http event with the LAMBDA-PROXY integration // return { message: 'Go Serverless v1.0! Your function executed successfully!', event }; };
module.exports.hello shows the name of our function that we specified in the serverless.yaml . From there this is just a callback function. The function right now simply prints out a message, and will also print out what exactly is in the event object as well. I thought this was personally very nice as it just makes me be able to view what exactly is being thrown into the function at the time of execution. Anyways, lets just leave the file alone for now..
So we have our yaml file setup, along with the basic handler function created for us, lets Deploy .
To Deploy, lets run the following command:
root@damrkul2:~/lambda_example# serverless deploy Serverless: Packaging service... Serverless: Excluding development dependencies... Serverless: Creating Stack... Serverless: Checking Stack create progress... ..... Serverless: Stack create finished... Serverless: Uploading CloudFormation file to S3... Serverless: Uploading artifacts... Serverless: Uploading service .zip file to S3 (387 B)... Serverless: Validating template... Serverless: Updating Stack... Serverless: Checking Stack update progress... ................................ Serverless: Stack update finished... Service Information service: rekous-lambda-test stage: dev region: us-east-1 stack: rekous-lambda-test-dev api keys: None endpoints: GET - https://wjvddbj9h1.execute-api.us-west-2.amazonaws.com/dev/output functions: hello: rekous-lambda-test-dev-hello
Well, that was nice, it gave us a bunch of information. It let us know what values are for our serverless app, such as our service name, our region that it was deployed at.... and also our endpoints.
Let's now open up a web browser and go to https://wjvddbj9h1.execute-api.us-west-2.amazonaws.com/dev/output
Let me fix up this json better for us...
{ "message": "Go Serverless v1.0! Your function executed successfully!", "input": { "resource": "/output", "path": "/output", "httpMethod": "GET", "headers": { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en-US,en;q=0.9", "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", "Host": "z44jotnbnl.execute-api.us-east-1.amazonaws.com", "upgrade-insecure-requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36", "Via": "2.0 9e51263695f38a00aa0f5c6fd3665d71.cloudfront.net (CloudFront)", "X-Amz-Cf-Id": "MmxUpnzpXtRStcXgenHltuBAvi5unV-DntL8dHL5CjuhYngavDHsIQ==", "X-Amzn-Trace-Id": "Root=1-5b7ef966-0fe4b5d7febf36c9a1547718", "X-Forwarded-For": "136.162.34.1, 52.46.12.75", "X-Forwarded-Port": "443", "X-Forwarded-Proto": "https" }, "queryStringParameters": null, "pathParameters": null, "stageVariables": null, "requestContext": { "resourceId": "w01bsu", "resourcePath": "/output", "httpMethod": "GET", "extendedRequestId": "MFvoBHVeIAMFfwg=", "requestTime": "23/Aug/2018:18:13:58 +0000", "path": "/dev/output", "accountId": "841181805441", "protocol": "HTTP/1.1", "stage": "dev", "requestTimeEpoch": 1535048038561, "requestId": "4e0551fa-a700-11e8-bc26-1f336c444547", "identity": { "cognitoIdentityPoolId": null, "accountId": null, "cognitoIdentityId": null, "caller": null, "sourceIp": "136.162.34.1", "accessKey": null, "cognitoAuthenticationType": null, "cognitoAuthenticationProvider": null, "userArn": null, "userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36", "user": null }, "apiId": "z44jotnbnl" }, "body": null, "isBase64Encoded": false } }
So you can see when we go to that endpoint, our function is executed, and printed not only the message, but also all of the details of the event object.
Let's think about what this means..... In a matter of seconds I now have fully functional service up and running.
The Sky is the Limit! Are you excited about this? I am.
Okay, I've calmed down..... Let me get back to what I want to say...
Another nice feature about lambda is we can easily deploy as many stages as we want. Recall the previous ENDPOINT:
https://wjvddbj9h1.execute-api.us-west-2.amazonaws.com/dev/output ... Where we have /dev/ path. We can easily modify this to lets say "prod" for production. We simply run serverless deploy --stage prod and it deploys with a new endpoint url.
Okay 1 Function, big woop. Lets add another 1. Lets create an ECHO function, so we can add a method: post example. The echo function will simply read in the POST data, and print it back to the user.
Lets modify our serverless.yaml
# # Rekous First Lambda Function # service: rekous-lambda-test provider: name: aws runtime: nodejs8.10 functions: hello: handler: handler.hello events: - http: path: output/ method: get echo: handler: handler.echo events: - http: path: echo/ method: post
Pretty simple so far. I just copied and pasted the hello function, and did some renaming, and changed the method to post.
handler.js
Lets add our echo function. We are modeling our function to accept json. Our payload for our POST will be something like this
{"message":"A Rekous Message"}
Anyways, Lets add out function to handler.js to reflect that type of data being sent in... and simply return back the POST'ed data. Here is the new handler.js file
'use strict'; module.exports.hello = async (event, context) => { return { statusCode: 200, body: JSON.stringify({ message: 'Go Serverless v1.0! Your function executed successfully!', input: event, }), }; // Use this code if you don't use the http event with the LAMBDA-PROXY integration // return { message: 'Go Serverless v1.0! Your function executed successfully!', event }; }; module.exports.echo = async (event, context) => { // Parse the Body that contains our text POST JSON var input = JSON.parse(event.body); return { statusCode: 200, body: JSON.stringify({ reply: input.message, }), }; };
That looks about right..... Lets save it and re-deploy the function.
root@damrkul2:~/lambda_example# serverless deploy Serverless: Packaging service... Serverless: Excluding development dependencies... Serverless: Uploading CloudFormation file to S3... Serverless: Uploading artifacts... Serverless: Uploading service .zip file to S3 (466 B)... Serverless: Validating template... Serverless: Updating Stack... Serverless: Checking Stack update progress... .................... Serverless: Stack update finished... Service Information service: rekous-lambda-test stage: dev region: us-east-1 stack: rekous-lambda-test-dev api keys: None endpoints: GET - https://wjvddbj9h1.execute-api.us-west-2.amazonaws.com/dev/output POST - https://wjvddbj9h1.execute-api.us-west-2.amazonaws.com/dev/echo functions: hello: rekous-lambda-test-dev-hello echo: rekous-lambda-test-dev-echo Serverless: Removing old service artifacts from S3...
You can see now that our new function endpoint has been created.... And if you tried to open that in your webbrowser by itself, you will get an Missing Authentication Token because you tried to do a GET on a POST function...
So lets send a POST request to test it out ... using cURL from the command line...
root@damrkul2:~/lambda_example# curl -d '{"message":"Rekous Message"}' -X POST https://wjvddbj9h1.execute-api.us-west-2.amazonaws.com/dev/echo {"reply":"Rekous Message"}
So you can see here that we our function replied with the data we sent.... Just using these functions we can build out a serverless API very easily.
Lambda seems pretty easy to use, and I already have some fun ideas I could build using lambda functions. Do you?