- Intro
- Improvements/Additions
- Setup and Usage
- API Testing
- Automating Deployment and Testing
- Testing and Debugging
AWS: Lambda, API Gateway, DynamoDB
Serverless Framework: Nodejs runtime, CloudFormation
Postman: API testing
REST API for a todo app. Built from scratch (and improved) using original project as a reference. The Serverless team created it to be a guide or proof of concept, so it was purposely bare bones. It's still incredible how they have so many different types of examples up for the framework (it's at least 30).
-
Issue: the PUT method in update.js required both "text" and "checked" keys in request body
- Resolution: split up endpoint from
/todos/{id}
to/todos/{id}/text
and/todos/{id}/checked
- Resolution: split up endpoint from
-
Issue: Get requests for an invalid or nonexistent todo ID returned status 200.
- Resolution: now returns 403 Forbidden to hide existence of a resource from unauthorized user.
- Resolution: now returns 403 Forbidden to hide existence of a resource from unauthorized user.
-
Rather than forcing a certain "checked" state, I added an endpoint to toggle it
/todos/{id}/tcheck
-
Refactored DynamoDB calls into a helper function to get the todo item's original data before being overwritten (for logging and potential history purposes)
Please refer to their original project. I changed a few of the endpoints, so I'll give you a complete list of them next.
Note:
glh3x7xjak
will be replaced with your own API Gateway ID. I left mine in for you to test it out.
Create todo item
POST request:
https://glh3x7xjak.execute-api.us-east-1.amazonaws.com/dev/todos
Data:
{ "text": "<your todo>" }
List all todos
GET request:
https://glh3x7xjak.execute-api.us-east-1.amazonaws.com/dev/todos
Data:
<none>
Get a todo
GET request:
https://glh3x7xjak.execute-api.us-east-1.amazonaws.com/dev/todos/<id>
Data:
<none>
Update a todo's text
PUT request:
https://glh3x7xjak.execute-api.us-east-1.amazonaws.com/dev/todos/<id>/text
Data:
{ "text": "<your new todo text>" }
Update a todo's "checked" (aka done) status
PUT request:
https://glh3x7xjak.execute-api.us-east-1.amazonaws.com/dev/todos/<id>/check
Data:
{ "checked": true } or { "checked": false }
Toggle a todo's "checked" (aka done) status
PUT request:
https://glh3x7xjak.execute-api.us-east-1.amazonaws.com/dev/todos/<id>/tcheck
Data:
<none>
Delete a todo
PUT request:
https://glh3x7xjak.execute-api.us-east-1.amazonaws.com/dev/todos/<id>
Data:
<none>
The Postman test collection is located in api-tests.postman_collection.json
You can import the file into Postman's native app or run it via command line:
newman run api-tests.postman_collection.json
(this will run all tests)
One thing to note is that within a Postman test collection, there are folders that can contain requests.
Within those requests are the tests.
E.g: Collection > Folder > Request > Test(s)
Each API call has its own JavaScript file in /todos
. Test requests are grouped into folders according to that filename.
E.g: api-tests.postman_collection.json > create.js > Requests > Test(s)
To run a test for a specific API call/JavaScript file from the command line, enter:
newman run api-tests.postman_collection.json --folder <collection folder name>.js
For example:
If you wanted to run all the tests for create.js
,
newman run api-tests.postman_collection.json --folder create.js
Note:
The collection folder—in this case, create.js
—can be named anything. I just decided to keep it the same as the file name for clarity.
All tests can be run in isolation. Each has a pre-request script that are invoked to set up environment variables (e.g. id, text data, etc).
Tests will generate a random verb and random noun to send the body of the request for creating/updating todo items.
For example:
To test an update call to the API, it will send something like { "text": "navigate pixel" }
or { "text": "synthesize monitor" }
, which I thought was fun.
I included a simple bash script that will deploy a Lambda function (JavaScript file) and then run the associated tests.
./deploy-and-test-function.sh <javascript file>
(do not include the .js
extension)
For example:
If you made changes to create.js
and wanted to deploy that Lambda function to AWS and immediately run tests:
./deploy-and-test-function.sh create
If you get a permissions error, type chmod 0755 deploy-and-test-function.sh
to allow anyone to execute the script.
Only takes 1 positional argument (as of this writing). Either plan to use a for loop or flag arguments. I never needed to deploy and test more than one at a time so it wasn't needed.
Remember:
If you made any changes to the serverless.yml
file, those changes won't be included when you use the deploy function method. You need to run a full sls deploy -v
instead. Refer back to the original project for more info.
A major issue for serverless apps has always been testing. Deploying the entire application during development is not ideal. Even if you're deploying a single lambda function, which is much faster, it still interrupts your workflow.
Of course, testing Lambda functions locally is ideal. Tooling for this is still currently in development, so here are a couple options:
-
The Serverless Framework has
sls invoke local --function <your function>
. It merely emulates an AWS environment, so it's not exactly perfect. Probably suitable enough though. -
An alternative is to use the
serverless-sam
plugin. It will convert yourserverless.yml
template to a SAM template (CloudFormation template). With AWS SAM you can locally test and debug your app.