Recipe ID: hsts-r1
We offer HTML5, CSS3, JavaScript,Bootstrap, Angular.JS, WordPress Node.JS, React.JS, Joomla, Drupal, Vue.JS and more classes in self-paced video format starting at $60. Click here to learn more and register. For complete self-paced web design training, visit our Web design and development bundle page.
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 recipe, 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.
Pre Requisites
Learning Objectives
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
Copy
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
Copy
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
Copy
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');
});
Copy
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"
},
Copy
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
Copy
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"
}
Copy
Once that is done, create a database file that connections your express app to Mongo DB.
mkdir db && touch db/connect.js
Copy
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;
Copy
Here you create an asynchronous function that tries to connect to the DB and if it fails, it consoles out the error.
Next we have to create the Model for the post. This represents each post that goes into the database.
mkdir models && touch post.js
Copy
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;
Copy
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
Copy
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 = {};
Copy
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);
}
}
Copy
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){
}
}
Copy
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);
}
}
Copy
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);
}
}
Copy
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;
Copy
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
Copy
Inside of your server.js file, add
import posts from './routes/posts.routes';
app.use('/api', posts);
Copy
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();
Copy
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;
Copy
Once this is done, we should be ready to test our API.
Lets start off by creating a few posts. Run the server with
npm run-script start
Copy
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
Here the API has been built up, 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.
JavaScript and jQuery Introduction
PHP and MySQL Coding
Advance Website Design Using HTML and CSS
Cross-platform Native App Development Using HTML5, CSS3 and JavaScript
jQuery Programming for Beginners
Intro to Dreamweaver with Website Development Training
Adobe Muse Training Course
Introduction to the WordPress CMS
Introduction to the Joomla CMS
Mastering Drupal in 30 Hours
SQL Programming and Database Management
We offer private coding classes for beginners online and offline (at our Virginia site) with custom curriculum for most of our classes for $59 per hour online or $95 per hour in virginia. Give us a call or submit our Private Coding Classes for Beginners form to discuss your needs.