Setting up Express Routes
By: Rick Glascock
Tags: Expressjs, Node, Mongoose

Initial Setup

Heading over to VSCode’s terminal I install Express 4.14.1. I also install the node.js CORS package, which enables cross-origin resource sharing between resources. By default, browsers won’t allow servers from the same origin to talk, the situation we find ourselves in when working locally in development mode with say, an Express server running serving the APIs and a React site all running at localhost. This behavior is for security, but won’t be an issue running things locally. Installing the CORS package allows us to by pass this restriction.

I also install nodemon which will restart the Express server every time a change is made in the code — a real time saver when developing!

Next I install the BCrypt and JSONWebToken packages. Bcrypt will be used to hash and later verify passwords before storing them in the MongoDB User collection. JSONWebToken will create and later verify an encrypted token that can be sent back to the client and stored in the browser’s local storage. The token allows a user’s authorization to persist after closing down and reopening the browser, a new session. As an aside, there’s a passionate discussion about the best way to store JWTs, or even to use them at all, but that’s out of the scope of this article.

Here’s the initial setup of an instance of Express Server (app). The code also imports in our configured instance of Mongoose which allows us to access and communicate with our MongoDB database.

// index.js const express = require('express');

const cors = require('cors');

require('./db/mongoose'); const app = express();

const port = process.env.PORT || 3000;

app.use(express.json());

app.use(cors()); app.listen(port, () => {

console.log(`Server running on port ${port}`);

});

Here’s the project folder structure I use:

Express Router

I set up four different routers to keep the routers a manageable size. Each router is imported into index.js and added to the instance of the Express server:

// index.js const userRouter = require('./routers/user');

const listRouter = require('./routers/list');

const masterItemRouter = require('./routers/masterItems');

const categoriesRouter = require('./routers/categories'); ... app.use(userRouter);

app.use(listRouter);

app.use(masterItemRouter);

app.use(categoriesRouter);

Here is a URL plan I came up that I found very helpful when writing the routers. It includes the endpoint’s Method/URL, the parameters expected, as well as the intended success and error returns. I found this especially helpful when designing requests in the React frontend.

Express Router plan

The actual routers are fairly simple to put together. Here’s the User router:

// src/routers/user.js const express = require('express');

const User = require('../models/user');

const auth = require('../middleware/authentication'); const router = new express.Router(); /// routes module.exports = router;

We import express so we can create an instance of Router for the new router. We also need to import the User model to use when creating new Users. Auth is Express middleware (authentication.js) that checks if a token is present and verified. If so, the current user is returned. This allows us to easily setup authorized routes that are only accessible if a user is logged in.

Finally the router is exported.

Below I define a route that creates a new user. We add the HTTP method used by the specific route (POST in this case) and the router takes two arguments — the path and a callback (handler function). The callback has two or three arguments — req (request) and res(response), and optionally next which can be used to call multiple callbacks. The callback below checks if the password and confirmation match. If they do, the new user is created. GenerateAuthToken is Mongoose is a Mongoose schema method that generates the jwt, saves it in the User’s document and returns the jwt to the router to add to the response back to the client.