This post is also available in:
Español
This Express tutorial assumes that you have Node.js installed and Mongo DB. Here is a link to the github repo.
Express is an awesome framework for creating fast web APIs to interface with your SPA and because it’s also in Javascript, your entire codebase can be developed in 1 language. The makes it easier to use all of the same familiar tools if you’re integrating with React JS or Angular.
In this tutorial, we’ll create a simple blog API that returns a list of blog posts to the user. In later posts, we’ll cover JWT authentication and user relationships with MongoDB but for now, we’ll focus on basic CRUD.
Project Setup with NPM
In order to create our application, we’re first going to have to setup out npm configuration and make sure that we specify that our project uses the ES6 syntax.
Create a project folder in the command line by running
mkdir ExpressAPIBlog && cd ExpressAPIBlog
Now that you are in the directory, create a package.json and add you dev dependencies
npm init
npm install --save-dev babel-cli babel-preset-stage-0 babel-preset-env
This will allow for you to compile your ES6 code to ES5 so that it is understood by Express.JS and Node.
Now in order to actually build your application, you have to add each of these dependencies with npm.
npm install body-parser cuid express limax mongoose sanatize-html
Now that everything is installed, create a file called server.js
import express from 'express';
import bodyParser from 'body-parser';
let app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.get('/', (req, res) => res.send('Hello World!'));
app.listen(3005, () => {
console.log('server started - 3005');
});
Then add a script to your package.json file to run the server
"scripts": {
"start": "babel-node server.js --presets env",
"test": "echo \"Error: no test specified\" && exit 1"
},
Database Setup with Mongoose
Now that express is working, let’s set up a database connection.
First off, let’s create a config file that specifies our connection to the database instance
mkdir config && touch config/index.js
Open the file and add the port number and database connection string.
export default {
"port": 3005,
"mongoUrl": "mongodb://localhost:27017/express-api-blog",
"bodyLimit": "100kb"
}
Once that is done, create a database file that connections your express app to Mongo DB.
mkdir db && touch db/connect.js
import mongoose from 'mongoose';
import config from '../config/index';
mongoose.Promise = global.Promise;
const connectToDb = async () => {
try {
await mongoose.connect(config.mongoUrl, { useMongoClient: true });
}
catch (err) {
console.log(err);
}
}
export default connectToDb;
Here you create an asynchronous function that tries to connect to the DB and if it fails, it consoles out the error.
Creating the Model
Next we have to create the Model for the post. This represents each post that goes into the database.
mkdir models && touch post.js
Inside of this model we will add a title along with the post content, a date the post was created at, a slug that will be generated based on the title and a cuid which is an id number. Even though all Mongoose documents have a _id field by default, cuid is another great way to have collision resistant ids
import mongoose from 'mongoose';
const Schema = mongoose.Schema;
const postSchema = new Schema({
title: { type: 'String', required: true },
content: { type: 'String', required: true },
slug: { type: 'String', required: true },
cuid: { type: 'String', required: true },
dateAdded: { type: 'Date', default: Date.now, required: true },
});
let Post = mongoose.model('Post', postSchema);
export default Post;
Express Controller Actions
Now that we have our database setup and the model that we would like to use to populate the database, now we must figure out a way to allow the user to send requests to the API to create new posts. We could place all of the requests inside of the server.js file but it’s much cleaner to create a controller file.
mkdir controllers && touch controllers/post.controller.js
Inside of this controller we are going to need 5 CRUD functions. A get all, get by Id, create, update and delete.
import Post from '../models/post';
import cuid from 'cuid';
import slug from 'limax';
import sanitizeHtml from 'sanitize-html';
const PostController = {};
We’ve created a controller object to make it easy to export all of the functions that we’ll be creating.
The first function will actually be the getAll() function.
PostController.getAll = async (req, res) => {
try{
await Post.find().sort('-dateAdded').exec((err, posts) => {
if (err) {
res.status(500).send(err);
}
res.json({ posts });
});
}
catch(err){
res.send(err);
}
}
This function takes in the request, tries the function and returns a a list of posts or an err depending on where the error takes place.
Then we have the getPost function. This finds the post by it’s cuid and returns the post if it exists.
PostController.getPost = async (req, res) => {
try{
Post.findOne({ cuid: req.params.cuid }).exec((err, post) => {
if (err) {
res.status(500).send(err);
}
res.json({ post });
});
}
catch(err){
}
}
Next, we have the addPost function. This checks if either the title or content is not present, creates the post, sanitizes the content, then saves the Post to the database.
PostController.addPost = async (req, res) => {
try {
if (!req.body.post.title || !req.body.post.content) {
res.status(403).end();
}
const newPost = new Post(req.body.post);
// Sanitize inputs
newPost.title = sanitizeHtml(newPost.title);
newPost.content = sanitizeHtml(newPost.body);
newPost.slug = slug(newPost.title.toLowerCase(), { lowercase: true });
newPost.cuid = cuid();
newPost.save((err, saved) => {
if (err) {
res.status(500).send(err);
}
res.json({ post: saved });
});
}
catch (err) {
console.log(err);
}
}
UpdatePost is very similar to addPost except it finds the post by it’s cuid, then updates the fields.
PostController.updatePost = async (req, res) => {
try {
if (!req.body.post.title || !req.body.post.content) {
res.status(403).end();
}
Post.findOne({ cuid: req.params.cuid }).exec((err, post) => {
// Handle database errors
if (err) {
res.status(500).send(err);
} else {
post.title = req.body.post.title || post.title;
post.content = req.body.post.content || post.content;
console.log('Post about to be saved');
// Save
post.save((err, saved) => {
if (err) {
res.status(500).send(err)
}
res.json({ post: saved });
});
}
});
}
catch (err) {
console.log(err);
}
}
For the DELETE Request, we have deletePost. This takes the cuid and deletes the post with that id. At the end, we also export the controller.
PostController.deletePost = async (req, res) => {
try {
Post.findOne({ cuid: req.params.cuid }).exec((err, post) => {
if (err) {
res.status(500).send(err);
}
post.remove(() => {
res.status(200).end();
});
});
}
catch (err) {
console.log(err);
}
}
export default PostController;
Express Routing
Even though we now have our controller set up, we’ll need a way to access the routes in our controller. This can easily be done by creating a routing file. In your command line run
mkdir routes && touch routes/posts.routes.js
Inside of your server.js file, add
import posts from './routes/posts.routes';
app.use('/api', posts);
Now open your posts.routes file and import the express router and your controller.
import { Router } from 'express';
import PostController from '../controllers/post.controller';
const router = new Router();
This will allow for you to map get, post, put and delete requests to your controller methods.
// Get all Posts
router.get('/posts', (req, res) => {
PostController.getAll(req, res);
});
// Get one post by cuid
router.get('/posts/:cuid', (req, res) =>{
PostController.getPost(req,res);
});
// Add a new Post
router.post('/posts', (req, res) => {
PostController.addPost(req, res);
});
router.put('/posts/:cuid', (req, res) => {
PostController.updatePost(req, res);
});
// Delete a post by cuid
router.delete('/posts/:cuid', (req, res) => {
PostController.deletePost(req, res);
});
export default router;
Once this is done, we should be ready to test our API.
Testing API Routes with Insomnia
Lets start off by creating a few posts. Run the server with
npm run-script start
and create a few posts with

Express Blog API Create
Do this several time and then do a get request to return all posts

Get Request Express Blog API
You can also use a tool like Compass to view all of your MongoDB Documents

MongoCompass Expres Blog API
Now let’s try testing out getting a post by it’s id.

GetByCUID Express Blog API
Also by passing in the cuid and the modified contents, we can update the post.

Put Request Blog API Express
Finally we have the DELETE Request. This can be done just by passing in the cuid.

Delete-Request-Express-Blog-API
Conclusion
Currently setting up a REST API with ES6 currently requires a lot of tooling to compile the Javascript but it offers the ability to write cleaning, more maintainable code. In later posts, we’ll discuss adding user management and authentication to the API as well as build both a React and Angular client. To keep up with the project, visit the link to the github repo.
Codebrains Newsletter
Get weekly dev news and tutorials.
This post is also available in:
Español
About The Author: James Coonce
James Coonce is a programmer from Tampa Fl that has a love for golf, travel and language learning. When he's not hitting golf balls, he's probably watching foreign movies.
More posts by James Coonce