(Re)defining routes
Next, let's migrate our requestHandler function to Express. With Express, instead of defining a single request handler for all our routes, we can define request handlers for each route using the format app.METHOD('path', callback), where METHOD is the HTTP method of the request.
Therefore, replace our previous requestHandler function with an app.post call. This is our old implementation:
function requestHandler(req, res) {
if (req.method === 'POST' && req.url === '/users') {
// Handler logic for POST /user
} else {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, World!');
}
}
And this is our new implementation:
app.post('/users', (req, res) => {
// Handler logic for POST /user
});
The req and res objects passed by Express are identical to the ones passed by Node's http module; this is why we can reuse the same logic as before. Run the tests again and they should still all pass:
$ yarn run test:e2e
............
2 scenarios (2 passed)
12 steps (12 passed)
Our code using Express is much clearer than our original example; here, each route is defined in its own block. Furthermore, if a request comes in for an unspecified route, then a 404: Not Found response is automatically given. These small conveniences highlight one of the benefits of using a framework rather than programming your own implementation.
Furthermore, instead of using res.writeHead, we can use res.status and res.set:
# Without Express
res.writeHead(400, { 'Content-Type': 'application/json' });
# With Express
res.status(400);
res.set('Content-Type', 'application/json');
Similarly, instead of using res.end with JSON.stringify, we can use the new res.json method provided by Express.
res.end(JSON.stringify({ message: 'Payload should not be empty' })); // Without Express
res.json({ message: 'Payload should not be empty' }); // With Express