Creating APIs for a space delivery company
The need: one application, several APIs exposing various functionalities
The code generated by this example is available here.
Planet Express is a space delivery company that have two types of customers :
- Senders like MomCorp and the Slurm factory that use Planet Express services to deliver products
- Recipients like the Luna Park or the Mars Vegas Casinos that receive these products
Planet Express, as a futurist company, wants to provide serverless APIs, web and mobile applications for their customers.
- Senders need an API to create and track deliveries
- Recipients need an API to track and validate the reception of deliveries
- Planet Express also needs an API for its Back Office application that manage all deliveries
Following REST principles, a simplified API implementing these functionalities should expose these endpoints :
PUT /delivery
to create of a new deliveryGET /delivery/{id}
to allow to track a deliveryPATCH /delivery/{id}
to modify a deliveryDELETE /delivery/{id}
to delete a delivery
We state that a sender cannot modify a delivery once created and a recipient deletes a delivery when it receives it.
Planet Express wants to provide an Swagger
specification to document the endpoints for development teams that integrate
the services.
To avoid exposing and documenting endpoints not needed by some API consumers, Planet Express wants a specific API for each
type of client application : sender
, recipient
and back-office
.
These three APIs belong to the same application and share the same code base. The back-office
API will provide access to
all functionalities while the consumers of the sender
and the recipient
APIs will only have access to endpoints that are
useful for them.
sender |
recipient |
back-office |
|
---|---|---|---|
POST /delivery |
X | X | |
GET /delivery/{id} |
X | X | X |
PATCH /delivery/{id} |
X | ||
DELETE /delivery/{id} |
X | X |
We will not see the implementation of authentication and authorization here. Neither will we see the implementation of the
data access. These are aspects of the application that do not rely on Myrmex. They are implemented in node.js
modules that
could run in any execution environment.
The creation of the application with Myrmex
For each command used in the following sections, it is possible to see its documentation using myrmex <command> -h
. Note
that the Myrmex cli itself only contains the command myrmex new
. Other commands are injected by Myrmex plugins when the
cli is executed in the project folder.
Initialization of the project
We create a new Myrmex project named planet-express
.
npm install -g @myrmex/cli
myrmex new planet-express @myrmex/iam @myrmex/api-gateway @myrmex/lambda
cd planet-express
Creation of the Lambda containing the application logic
We are free to use as many Lambdas as we want in a Myrmex project. For example, we could associate one specific Lambda for each endpoint. But the Planet Express development team choose to put all the logic of the application in one single Lambda. Parameters provided by API Gateway will allow the lambda to know which portions of code to execute.
The implementation of the Lambda and of the modules is out of the scope of this tutorial. We will create them and leave them empty. This will give an overview of the structure of a Myrmex project and show the integration of Lambdas with API Gateway. Myrmex helps you to organize and deploy serverless projects, but it does not interfere about how you write Node.js code.
Creation of the Lambda's execution role
The Lambda needs to be associated to an IAM role that defines its authorizations in AWS. It could be authorized to access DynamoDB, RDS or S3 depending on the implementation of the application. For now, we use a role that allows the Lambda to write logs in CloudWatch.
myrmex create-role PlanetExpressLambdaExecution --model LambdaBasicExecutionRole
Creation of node modules that can be packaged in the Lambda
Myrmex allows the creation of node modules that can be embedded in the package of the Lambda. The development team decided that they will need two modules:
- A logging module that should allow to write logs in various backends (Cloudfront, S3, a database, etc ...)
- A module that manage the access to the application data (DynamoDB, Sequelize, mongoose, etc ...)
The data access module uses the logging module. We indicate this dependency so that if a Lambda requires the data access module, it will include the logging module in its package too.
myrmex create-node-module log
myrmex create-node-module data-access --dependencies log
The implementation of the modules will not be detailed here, but they are "common" node.js
modules that could be used in any execution environment.
Creation of a Lambda
We create a Lambda, specifying its configuration and its dependencies.
myrmex create-lambda api-generic --runtime nodejs6.10 --timeout 20 --memory 256 --role PlanetExpressLambdaExecution --dependencies data-access,log
Creation of the endpoints and APIs
Now that we have a Lambda able to perform the operations needed by our application, we can define the endpoints that integrate with it and expose them in various APIs.
Creation of the APIs
We create one API for each type of client application.
myrmex create-api back-office --title "Back Office" --desc "Planet Express API for Back Office"
myrmex create-api sender --title "Sender" --desc "Planet Express API for sender application"
myrmex create-api recipient --title "Recipient" --desc "Planet Express API for recipient application"
Creation of the invocation role
The API endpoints need to be associated to an IAM role that allows to invoke the Lambda.
myrmex create-role PlanetExpressLambdaInvocation -m APIGatewayLambdaInvocation
Creation of the endpoints
We create the four endpoints and associate them to the APIs that have to expose them.
myrmex create-endpoint /delivery/{id} get --apis back-office,recipient,sender --summary "View a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex create-endpoint /delivery/{id} patch --apis back-office --summary "Update a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex create-endpoint /delivery post --apis back-office,sender --summary "Create a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex create-endpoint /delivery/{id} delete --apis back-office,recipient --summary "Delete a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
Deployment
We deploy the stage v0
of the three APIs on the DEV
environment.
myrmex deploy-apis back-office sender recipient --region us-east-1 --stage v0 --environment DEV --deploy-lambdas all --alias ""
Altogether
npm install -g @myrmex/cli
myrmex new planet-express @myrmex/iam @myrmex/api-gateway @myrmex/lambda
cd planet-express
myrmex create-role PlanetExpressLambdaExecution --model LambdaBasicExecutionRole
myrmex create-node-module log
myrmex create-node-module data-access --dependencies log
myrmex create-lambda api-generic --runtime nodejs6.10 --timeout 20 --memory 256 --role PlanetExpressLambdaExecution --dependencies data-access,log
myrmex create-api back-office --title "Back Office" --desc "Planet Express API for Back Office"
myrmex create-api sender --title "Sender" --desc "Planet Express API for sender application"
myrmex create-api recipient --title "Recipient" --desc "Planet Express API for recipient application"
myrmex create-role PlanetExpressLambdaInvocation -m APIGatewayLambdaInvocation
myrmex create-endpoint /delivery/{id} get --apis back-office,recipient,sender --summary "View a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex create-endpoint /delivery/{id} patch --apis back-office --summary "Update a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex create-endpoint /delivery post --apis back-office,sender --summary "Create a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex create-endpoint /delivery/{id} delete --apis back-office,recipient --summary "Delete a delivery" --integration lambda-proxy --auth none --role PlanetExpressLambdaInvocation --lambda api-generic
myrmex deploy-apis back-office sender recipient --region us-east-1 --stage v0 --environment DEV --deploy-lambdas all --alias ""