In this project, we will create a node server that will act as a bookshelf. This server will keep track of books by being able to add books to a collection, read from the collection, update the collection, and delete from the collection. We'll use postman to test our endpoints.
Forkthis repository.Cloneyourfork.
In this step, we will create a package.json to keep track of our server's packages.
- Run
npm init -y.
In this step, we will install the most common packages you'll use when making a node server.
- Run
npm install express
In this step, we will create a .gitignore file to ignore the node_modules folder npm install created.
- Create a
.gitignorefile in the root of the project. - Add
node_moduleson the first line and save the file.
.gitignore
node_modules
In this step, we will create our server and have it listen on port 4000.
- In the root of the directory create a folder called
server. - Create an
index.jsfile inserver/. - Open
server/index.js. - Require
expressin a variable calledexpress. - Create a variable called
appthat equalsexpressinvoked. - Call the
usemethod on app and pass in theexpress.jsonmethod invoked. - Call the
listenmethod on app. The app should listen on port 4000:- The first parameter of
listenis the port number. - The second parameter of
listenis a function that is called when the app starts listening.
- The first parameter of
server/index.js
const express = require('express');
const app = express();
app.use(express.json());
const port = 4000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});In this step, we will create a controller that keeps track of the book collection and import that controller into server/index.js.
- Create a folder in
server/calledcontrollers. - In
server/controllers/create a file calledbooks_controller.js. - Open
server/controllers/books_controller.js. - Create a variable called
booksthat equals an empty array.- The
booksvariable will keep track of all our books. A book will be an object that has anid,title, andauthorproperty.
- The
- Create a variable called
idthat equals0.- After a creation of a book, we will increment this by
1to insure no books have the sameid.
- After a creation of a book, we will increment this by
- Use
module.exportsto export an object. - Open
server/index.js. - Require the books controller at the top of
server/index.jsin a variable calledbc.
server/controller/books_controller.js
let books = [];
let id = 0;
module.exports = {}; server/index.js
const express = require("express");
const bc = require("./controllers/books_controller.js");
const app = express();
app.use(express.json());
const port = 4000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});In this step, we will create the endpoint to get all the books. We will also create the method in the books_controller to be used as the endpoint's handler function.
When creating a get route, you can use the get method on the app object. The first argument is the URL of the request and the second argument is the function to execute when that URL is hit. We will be getting that function from the books_controller.
- Open
server/index.js. - Below the top level middleware and above the listen method invocation, add a
getendpoint.- The URL path should be
/api/books. - The handler function will come from the
books_controller, we will add it once we create it.
- The URL path should be
- Open
server/controllers/books_controller.js. - Create a method called
readin themodule.exportsobject.- This method should return all the books.
- Return to the
getendpoint inserver/index.jsthat we just wrote and add thereadmethod as the second argument after the URL path.
server/controller/books_controller.js
let books = [];
let id = 0;
module.exports = {
read: (req, res) => {
res.status(200).send(books);
}
}; server/index.js
const express = require("express");
const bc = require("./controllers/books_controller.js");
const app = express();
app.use(express.json());
app.get("/api/books", bc.read);
const port = 4000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});In this step, we will create the endpoint to post a new book. We will also create the method in the books_controller to be used as the endpoint's handler function.
- Open
server/index.js. - Below the
getendpoint, add apostendpoint.- The URL path should be
/api/books. - The handler function will come from the
books_controller, we will add it once we create it.
- The URL path should be
- Open
server/controllers/books_controller.js. - Create a method called
createin themodule.exportsobject.- This method should add a new book from the request body to the
booksarray. - When finished, it should return all the books.
- Keep in mind, the information you'll be getting from the request body are
titleandauthor. You'll have to add your own id property with the value coming from theidvariable. Don't forget to increment theidvariable when you're done.
- This method should add a new book from the request body to the
- Return to the
postendpoint inserver/index.jsthat we just wrote and add thecreatemethod as the second argument after the URL path.
server/controller/books_controller.js
let books = [];
let id = 0;
module.exports = {
read: (req, res) => {
res.status(200).send(books);
},
create: (req, res) => {
const { title, author } = req.body;
let book = {
id: id,
title: title,
author: author
}
books.push(book);
id++;
res.status(200).send(books);
}
}; server/index.js
const express = require("express");
const bc = require("./controllers/books_controller.js");
const app = express();
app.use(express.json());
app.get("/api/books", bc.read);
app.post("/api/books", bc.create);
const port = 4000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});In this step, we will create a put endpoint to update a specific book by it's id. We will also create the method in the books_controller to be used as the endpoint's handler function.
- Open
server/index.js. - Below the
postendpoint, add aputendpoint.- You will be using the
paramsobject in this endpoint, specifically an id you'll get from the URL parameters. Make sure to indicate this at the end of the URL path/api/books. - The handler function will come from the
books_controller, we will add it once we create it.
- You will be using the
- Open
server/controllers/books_controller.js. - Create a method called
updatein themodule.exportsobject.- This method should find a specific book based off of an id that you'll get off of the
paramsobject. - Once the book is found, update the book with the new information you'll get off of the request body.
- Return all the books.
- This method should find a specific book based off of an id that you'll get off of the
- Return to the
putendpoint inserver/index.jsthat we just wrote and add theupdatemethod as the second argument after the URL path.
server/controller/books_controller.js
let books = [];
let id = 0;
module.exports = {
read: (req, res) => {
res.status(200).send(books);
},
create: (req, res) => {
const { title, author } = req.body;
let book = {
id: id,
title: title,
author: author
};
books.push(book);
id++;
res.status(200).send(books);
},
update: (req, res) => {
let index = null;
books.forEach((book, i) => {
if (book.id === Number(req.params.id)) index = i;
});
books[index] = {
id: books[index].id,
title: req.body.title || books[index].title,
author: req.body.author || books[index].author
};
res.status(200).send(books);
}
}; server/index.js
const express = require("express");
const bc = require("./controllers/books_controller.js");
const app = express();
app.use(express.json());
app.get("/api/books", bc.read);
app.post("/api/books", bc.create);
app.put("/api/books/:id", bc.update);
const port = 4000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});In this step, we will create a delete endpoint to delete a specific book by it's id. We will also create the method in the books_controller to be used as the endpoint's handler function.
- Open
server/index.js. - Below the
putendpoint, add adeleteendpoint.- You will be using the
paramsobject in this endpoint, specifically an id you'll get from the URL parameters. Make sure to indicate this at the end of the URL path/api/books. - The handler function will come from the
books_controller, we will add it once we create it.
- You will be using the
- Open
server/controllers/books_controller.js. - Create a method called
deletein themodule.exportsobject.- This method should find a specific book based off of an id that you'll get off of the
paramsobject. - Once the book is found, remove that book from the
booksarray. - Return all the books.
- This method should find a specific book based off of an id that you'll get off of the
- Return to the
deleteendpoint inserver/index.jsthat we just wrote and add thedeletemethod as the second argument after the URL path.
server/controller/books_controller.js
let books = [];
let id = 0;
module.exports = {
read: (req, res) => {
res.status(200).send(books);
},
create: (req, res) => {
const { title, author } = req.body;
let book = {
id: id,
title: title,
author: author
};
books.push(book);
id++;
res.status(200).send(books);
},
update: (req, res) => {
let index = null;
books.forEach((book, i) => {
if (book.id === Number(req.params.id)) index = i;
});
books[index] = {
id: books[index].id,
title: req.body.title || books[index].title,
author: req.body.author || books[index].author
};
res.status(200).send(books);
},
delete: (req, res) => {
let index = null;
books.forEach((book, i) => {
if (book.id === Number(req.params.id)) index = i;
});
books.splice(index, 1);
res.status(200).send(books);
}
}; server/index.js
const express = require("express");
const bc = require("./controllers/books_controller.js");
const app = express();
app.use(express.json());
app.get("/api/books", bc.read);
app.post("/api/books", bc.create);
app.put("/api/books/:id", bc.update);
app.delete("/api/books/:id", bc.delete);
const port = 4000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});In this step, we will use Postman Unit Tests to test our endpoints.
- Start up (or restart) your server.
- Open Postman.
- Click on the
Importbutton and then click onChoose Files. - Select the
postman_collection.jsonfile from the root of the project. - Click on the arrow next to the
node_introductioncollection and click onRun. - In the new Postman window make sure
node_introductionis highlighted in orange and then pressStart Test.- It's important to know that if you try to run the tests again, you must restart your server first or your tests will fail.
In this step, we will use express.static to serve up our index.html file. express.static takes an argument that is the location of the folder with the files you want to serve when the server URL is hit in a browser. Our front-end was made using create-react-app and instead of running it's own server, we have made a production ready build so that our server can serve up our frontend. We'll want to serve the entire build folder.
- Call the
usemethod on app and pass inexpress.static( __dirname + '/../build'). - Add some books to your collection using Postman.
- Open up
http://localhost:4000in your browser.
server/index.js
const express = require("express");
const bc = require("./controllers/books_controller.js");
const app = express();
app.use(express.json());
app.use(express.static(__dirname + "/../build"));
app.get("/api/books", bc.read);
app.post("/api/books", bc.create);
app.put("/api/books/:id", bc.update);
app.delete("/api/books/:id", bc.delete);
const port = 4000;
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});If you see a problem or a typo, please fork, make the necessary changes, and create a pull request so we can review your changes and merge them into the master repo and branch.
© DevMountain LLC, 2017. Unauthorized use and/or duplication of this material without express and written permission from DevMountain, LLC is strictly prohibited. Excerpts and links may be used, provided that full and clear credit is given to DevMountain with appropriate and specific direction to the original content.




