Now that your API is live, let’s test it out. You’ll walk through a quick explanation of the code before testing one of your endpoints.
The web application is built using Express.js, a popular Node.js web application framework. You don’t need to use an existing web framework like Express.js when building applications on AWS Lambda, but it can ease the learning curve if you have experience with Express.
The core of the Express application is located in application/app.js. Open the file in the file explorer.
// application/app.js
const express = require("express");
const bodyParser = require("body-parser");
const { createGame, fetchGame, performMove, handlePostMoveNotification } = require("./data");
const {
createCognitoUser,
login,
fetchUserByUsername,
verifyToken
} = require("./auth");
const { validateCreateUser, validateCreateGame, validatePerformMove } = require("./validate");
const app = express();
app.use(bodyParser.json());
function wrapAsync(fn) {
return function(req, res, next) {
fn(req, res, next).catch(next);
};
}
// Login
app.post("/login", wrapAsync(async (req, res) => {
const idToken = await login(req.body.username, req.body.password);
res.json({ idToken });
}));
// Create user
app.post("/users", wrapAsync(async (req, res) => {
const validated = validateCreateUser(req.body);
if (!validated.valid) {
throw new Error(validated.message);
}
const user = await createCognitoUser(
req.body.username,
req.body.password,
req.body.email,
req.body.phoneNumber
);
res.json(user);
}));
// Create new game
app.post("/games", wrapAsync(async (req, res) => {
const validated = validateCreateGame(req.body);
if (!validated.valid) {
throw new Error(validated.message);
}
const token = await verifyToken(req.header("Authorization"));
const opponent = await fetchUserByUsername(req.body.opponent);
const game = await createGame({
creator: token["cognito:username"],
opponent: opponent
});
res.json(game);
}));
// Fetch game
app.get("/games/:gameId", wrapAsync(async (req, res) => {
const game = await fetchGame(req.params.gameId);
res.json(game);
}));
// Perform move
app.post("/games/:gameId", wrapAsync(async (req, res) => {
const validated = validatePerformMove(req.body);
if (!validated.valid) {
throw new Error(validated.message);
}
const token = await verifyToken(req.header("Authorization"));
const game = await performMove({
gameId: req.params.gameId,
user: token["cognito:username"],
changedHeap: req.body.changedHeap,
changedHeapValue: req.body.changedHeapValue
});
let opponentUsername
if (game.user1 !== game.lastMoveBy) {
opponentUsername = game.user1
} else {
opponentUsername = game.user2
}
const opponent = await fetchUserByUsername(opponentUsername);
const mover = {
username: token['cognito:username'],
phoneNumber: token['phone_number']
}
await handlePostMoveNotification({ game, mover, opponent })
res.json(game);
}));
app.use(function(error, req, res, next) {
res.status(400).json({ message: error.message });
});
module.exports = app;
At the top of this file, you import express and other dependencies, including the authentication helper functions and data access functions that you reviewed in previous modules. Then, you configure the various routes you want in your function, such as /login for a user to login and fetch an ID token or /games/:gameId to fetch the status of a particular game. Finally, at the bottom of the file, the script exports the Express application.
Next, look at application/handler.js. This is the file with the entrypoint method that you tell Lambda to invoke on an incoming request. The contents of this file are as follows:
// application/handler.js
const awsServerlessExpress = require('aws-serverless-express')
const app = require('./app')
const server = awsServerlessExpress.createServer(app)
exports.handler = (event, context) => { awsServerlessExpress.proxy(server, event, context) }
This handler is using the aws-serverless-express package. This package converts an incoming API Gateway request into the standard request expected by the Express.js framework. This makes it easy to run Express.js code using Lambda and API Gateway.
Let’s test your endpoint by fetching the game you created in an earlier module. This request goes through API Gateway to your Lambda function, which then makes a request to DynamoDB and returns the results.
Run the following command in your terminal:
You should see the following output in your terminal:
{"heap2":4,"heap1":3,"heap3":5,"gameId":"5b5ee7d8","user2":"theseconduser","user1":"myfirstuser","lastMoveBy":"theseconduser"}
Success! You hit your API endpoint. This triggered your Lambda function, which retrieved the game details for your requested game from DynamoDB.