Deploy A REST API Using Serverless, Express and Node - Js
Deploy A REST API Using Serverless, Express and Node - Js
sign-up free
Deploy a simple API endpoint
Add a DynamoDB table and two endpoints to create and retrieve a User object
Search blogs Set up path-specific routing for more granular metrics and monitoring
Configure your environment for local development for a faster development
experience.
But moving to serverless has a learning curve as well. You need to learn the intricacies of
the platform you're using, including low-level details like format of the request input and
the required shape of the response output. This can get in the way and slow your Then, let's install a few dependencies. We'll install the express framework, as well as the
development process. serverless-http :
Today, I come with good news: your existing web framework tooling will work seamlessly
with Serverless. In this post, I'll show you how to use the popular Node web framework $ npm install --save express serverless-http
Express.js to deploy a Serverless REST API. This means you can use your existing code +
💥
the vast Express.js ecosystem while still ge ing all the benefits of Serverless !
provider:
// index.js
name: aws
runtime: nodejs6.10
const serverless = require('serverless-http');
stage: dev
const express = require('express')
region: us-east-1
const app = express()
functions:
app.get('/', function (req, res) {
app:
res.send('Hello World!')
handler: index.handler
})
events:
- http: ANY /
module.exports.handler = serverless(app);
- http: 'ANY {proxy+}'
This is a very simple application that returns "Hello World!" when a request comes in
This is a pre y basic configuration. We've created one function, app , which uses the
on the root path / .
exported handler from our index.js file. Finally, it's configured with some HTTP triggers.
It's straight out of the Express documentation with two small additions. First, we
We've used a very broad path matching so that all requests on this domain are routed to
imported the serverless-http package at the top. Second, we exported a handler
this function. All of the HTTP routing logic will be done inside the Express application.
function which is our application wrapped in the serverless package.
subscribe subscribe
backing store.
$ sls deploy
... snip ...
For this simple example, let's say we're storing Users in a database. We want to store
Service Information
service: my-express-application them by userId , which is a unique identifier for a particular user.
stage: dev
region: us-east-1 First, we'll need to configure our serverless.yml to provision the table. This involves
stack: my-express-application-dev
three parts:
api keys:
None
endpoints: . Provisioning the table in the resources section;
ANY - https://bl4r0gjjv5.execute-api.us-east-1.amazonaws.com/dev . Adding the proper IAM permissions; and
ANY - https://bl4r0gjjv5.execute-api.us-east-1.amazonaws.com/dev/{proxy+ . Passing the table name as an environment variable so our functions can use it.
functions:
app: my-express-application-dev-app
Change your serverless.yml to look as follows:
A er a minute, the console will show your endpoints in the Service Information # serverless.yml
section. Navigate to that route in your browser:
service: my-express-application
custom:
tableName: 'users-table-${self:provider.stage}'
provider:
name: aws
runtime: nodejs6.10
stage: dev
region: us-east-1
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
Your application is live! - dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Adding a DynamoDB table with REST-like Resource:
const params = {
TableName: USERS_TABLE,
$ curl -H "Content-Type: application/json" -X POST ${BASE_DOMAIN}/users -d
Item: {
{"userId":"alexdebrie1","name":"Alex DeBrie"}
userId: userId,
name: name,
},
};
Nice! We've created a new user! Now, let's retrieve the user with the GET /users/:userId`
dynamoDb.put(params, (error) => { endpoint:
if (error) {
console.log(error);
res.status(400).json({ error: 'Could not create user' });
$ curl -H "Content-Type: application/json" -X GET ${BASE_DOMAIN}/users/alex
}
{"userId":"alexdebrie1","name":"Alex DeBrie"}
res.json({ userId, name });
});
})
This isn't a full-fledged REST API, and you'll want to add things like error handling,
authentication, and additional business logic. This does give a framework in which you
In addition to base "Hello World" endpoint, we now have two new endpoints:
can work to set up those things.
functions:
$ sls deploy
app:
handler: index.handler
events:
- http: ANY /
- http: 'ANY {proxy+}'
We'll use curl for these examples. Set the BASE_DOMAIN variable to your unique domain
and base path so it's easier to reuse:
subscribe We're forwarding all traffic on the domainsubscribe
to our application and le ing Express handle
h i f h i l i Th i b fi hi I d ' h ll i
your application, and all requests to POST /users/ will be handled by the createUser
the entirety of the routing logic. There is a benefit to this—I don't have to manually string
instance. For any other requests, they'll be handled by the main app instance of your
up all my routes and functions. I can also limit the impact of cold-starts on lightly-used
function.
routes.
Again, none of this is required, and it's a bit of an overweight solution since each specific
However, we also lose some of the benefits of the serverless architecture. I can isolate my
endpoint will include the full application code for your other endpoints. However, it's a
bits of logic into separate functions and get a decent look at my application from
standard metrics. If each route is handled by a different Lambda function, then I can see: good balance between speed of development by using the tools you're used to along
with the per-endpoint granularity that serverless application pa erns provide.
How many times each route is invoked
How many errors I have for each route
How long each route takes (and how much money I could save if I made that route Local development configuration with
faster)
Serverless offline plugin
Luckily, you can still get these things if you want them! You can configure your
When developing an application, it's nice to rapidly iterate by developing and testing
serverless.yml so that different routes are routed to different instances of your
locally rather than doing a full deploy between changes. In this section, I'll show you how
function.
to configure your environment for local development.
Each function instance will have the same code, but they'll be segmented for metrics
First, let's use the serverless-offline plugin. This plugin helps to emulate the API
purposes:
Gateway environment for local development.
functions:
app: $ npm install --save-dev serverless-offline
handler: index.handler
events:
- http: ANY /
- http: 'ANY {proxy+}'
Then add the plugin to your serverless.yml :
getUser:
handler: index.handler
events:
- http: 'GET /users/{proxy+}' # serverless.yml
createUser:
handler: index.handler plugins:
events: - serverless-offline
Luckily, there's a plugin for doing local development with a local DynamoDB emulator!
We'll use the serverless-dynamodb-local plugin for this.
Finally, we need to make some small changes to our application code. When instantiating
our DynamoDB client, we'll add in some special configuration if we're in a local, offline
It works! If you make a change in your index.js file, it will be updated the next time you environment. The serverless-offline plugin sets an environment variable of
hit your endpoint. This rapidly improves development time. IS_OFFLINE to true , so we'll use that to handle our config. Change the beginning of
index.js to the following:
While this works easily for a stateless endpoint like "Hello World!", it's a li le trickier for
subscribe subscribe
our /users endpoints that interact with a database.
running locally or uses the default options if running in Lambda.
functions:
This local setup can really speed up your workflow while still allowing you to emulate a app:
close approximation of the Lambda environment. handler: app.handler
events:
- http: ANY /
If you already have an existing Express application, it's very easy to convert to a
Serverless-friendly application. Do the following steps:
That's it! Run sls deploy and your app will deploy!
# serverless.yml
service: express-app
provider:
name: aws
runtime: nodejs6.10
stage: dev subscribe subscribe
region: us east 1
express framework, is that not a good way to create APIs ?
2 ) Can i create local serverless environment and mongodb
environment in every context ?
3) Where it is preferred to create REST APIs using the way given in
article and the lambda function API way ?
Thank You.
44 △ ▽ • Reply • Share ›
About Alex DeBrie For 1 & 3, it's completely fine to make Node APIs without the
Express framework. I've written this example as an easier
Alex DeBrie is a data engineer at Serverless. on-ramp for those who are already familiar with Express or
who want to move existing Express applications over. If
you're happy with using the Lambda functions directly, go for
it!
4△ ▽ • Reply • Share › question, does it mean that each lambda call we are building
complete api instance that can accept all of the endpoints ?
memelorde • 8 hours ago • edited or something behind the scene split all the endpoints into
if you're getting an error telling you to upgrade node js runtime, in independent functions before deploy ?
serverless.yml change it to this
thanks
provider: △ ▽ • Reply • Share ›
runtime: 12.x
and everything else ANSHUL NEGI • 2 years ago
S });
△ ▽ • Reply • Share ›
<html lang="en"><head>
<meta charset="utf-8"> pirahana • 2 years ago
<title>Error</title> Hi, the article is great. I needed one help, if possible can use write
</head> an example where we deploy a these APIs with a custom lambda
<body> authorizer which is in some other domain. I am trying the same.
This is my serverless.yml file,
Cannot POST /invUpdateApp-dev-app
provider:
</body>
name: aws
</html>
runtime: nodejs10.x
△ ▽ • Reply • Share › stage: dev
subscribe region: us-east-1 subscribe
Carlos Villegas > Adam Berk • 7 months ago
function without having to redeploy all of them? I tried sls deploy
functions: function -f myFunction. It updated the code in lambda but I cannot
app: see the change when I invoke it.
handler: app.server △ ▽ • Reply • Share ›
events:
- http: Narendra Kothule • 3 years ago
path: / Nice Article!!
method: ANY Do you have any reference to deploy serverless app using Express
cors tr e on Azure Function app service?
see more Thank you.
△ ▽ • Reply • Share › △ ▽ • Reply • Share ›
△ ▽ • Reply • Share › in params When I execute. shows: Missing required key 'Bucket'
△ ▽ • Reply • Share ›
Diego R FG • 3 years ago
Really really really helpful!!! Is there a way to deploy a specific
subscribe Sridhar Duggireddy • 3 years ago
subscribe
function without having to redeploy all of them? I tried sls deploy Hi Thank you for the article I noticed that there are some
Hi, Thank you for the article. I noticed that there are some
Coming from koa/expressJS background, this is a good article to
differences in syntax in serverless.yml with the new serverless
get started with Serverless Framework.
framework. Also, I noticed that serverless.yml is missing
DynamoDBIamPolicy segment. I had to add it to authorize my app
correctly. This is what I added.
DynamoDBIamPolicy:
Type: AWS::IAM::Policy
DependsOn: UsersDynamoDBTable New to serverless?
Properties:
PolicyName: lambda-dynamodb To get started, pop open your terminal & run:
PolicyDocument: npm install serverless -g
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- dynamodb:GetItem documentation
- dynamodb:PutItem
Resource: arn:aws:dynamodb:*:*:table/${self:custom.tableName}
Roles: examples
- Ref: IamRoleLambdaExecution
△ ▽ • Reply • Share › plugins
Narendra Kothule > Scott Jones • 3 years ago e-mail address subscribe
Hi Scott, I am also looking for serverless application using
express to deploy on Azure Functions app. did you used
azure function app service? do you have any reference?
Thanks
[email protected] - Copyright © 2021 Serverless, Inc. All rights reserved.
△ ▽ • Reply • Share ›
JF • 3 years ago
The demo did not create any endpoints...
△ ▽ • Reply • Share ›