REST

Resources

Resources are either specific objects within the system or collections of objects. They should always be addressable by a URL.

Resources should always be named plural, because they are collections with specific objects within.

Verbs

GET

Requests a resource.

POST

creates a resource. Also used to issue ad-hoc/unsafe API commands that don’t fit in the REST framework. (non-idempotent)

PUT

Updates a resource

DELETE

Removes a resource

Idempotent

If we can do the same action over and over again and see the same result, an action is idempotent. GET, PUT, and DELETE should all be idempotent actions. If you wish to do something that can be repeated for different results, use POST.

Express Projects

Install Express npm install --save express

index.js
let express = require('express');
let bodyParser = require('body-parser');
let routes = require('./lib/routes');

let port = 6061;

let app = express();

app.use(bodyParser.json())

app.use('/', routes);

app.listen(port, function() {
    console.log("Listening on :%d", port);
});
lib/routes.js
-let express = require('express');
let companies = require('./controllers/companies');

let routes = express.Router();

routes.get('/companies', companies.root);

routes.get('/companies/:companyName', companies.name)

routes.get('/companies/:companyName/employees', companies.employees)

routes.route('/companies/:companyName/employees/:employeeName')
    .get(companies.singleEmployee)
    .put(companies.createEmployee)
    .delete(companies.removeEmployee)

module.exports = routes;
lib/controllers/companies.js
let data = require('../../data/data');

module.exports = {
    root: (req, res) => {
        let names = [];
        for (let key in data.companies) {
            names.push(key);
        }
        res.json(names);
    },
    name: (req, res) => {
        let name = req.params.companyName;
        if (data.companies.hasOwnProperty(name)) {
            res.json(data.companies[name]);
            return
        }
        res.status(404);
        res.send('not found');
    },
    employees: (req, res) => {
        let name = req.params.companyName;
        if (data.companies.hasOwnProperty(name)) {
            res.json(data.employees[name]);
            return
        }
        res.status(404);
        res.send('not found');
    },
    singleEmployee: (req, res) => {
        let companyName = req.params.companyName;
        let employeeName = req.params.employeeName;

        if (!data.employees.hasOwnProperty(companyName)) {
            res.status(404);
            res.json('company not found');
            return;
        }

        for (let e of data.employees[companyName]) {
            if (e.name === employeeName) {
                res.json(e);
                return
            }
        }

        res.status(404);
        res.json('employee not found');
    },
    createEmployee: (req, res) => {
        let companyName = req.params.companyName;
        let employeeName = req.params.employeeName;
        let body = req.body;

        if (body['name'] !== employeeName) {
            res.status(400);
            res.json({error: "name does not match request employee name"});
            return;
        }

        if (!body['job']) {
            res.status(400);
            res.json({error: "employee job not specified"});
            return;
        }

        if (!data.employees.hasOwnProperty(companyName)) {
            res.status(404);
            res.json('company not found');
            return;
        }

        data.employees[companyName] = data.employees[companyName].filter(value => { return value.name !== employeeName; });

        data.employees[companyName].push(body);
        res.sendStatus(204);
    },
    removeEmployee: (req, res) => {
        let companyName = req.params.companyName;
        let employeeName = req.params.employeeName;

        // let a = [1, 2, 3];
        // a.filter((value => { return value === 1; }))

        if (!data.employees.hasOwnProperty(companyName)) {
            res.status(404);
            res.json('company not found');
            return;
        }

        data.employees[companyName] = data.employees[companyName].filter(value => { return value.name !== employeeName; });

        res.sendStatus(204);
    },
}
data/data.js
module.exports = {
    companies: {
        "InnitechCorp": {
            id: 0,
            name: "Innitech Corp",
            numberOfEmployees: 50
        },
        "InnitrodeCorp": {
            id: 1,
            name: "Innitrode Corp",
            numberOfEmployees: 54
        },
        "ReynholmIndustries": {
            id: 23,
            name: "Reynholm Industries",
            numberOfEmployees: 60
        }
    },
    employees: {
        "InnitechCorp": [
            {
                name: "Peter",
                job: "Paper Pusher"
            },
            {
                name: "Bob Slydell",
                job: "Consultant"
            },
            {
                name: "Bob Porter",
                job: "Consultant"
            }
        ],
        "InnitrodeCorp": [
            {
                name: "Michael Bolton",
                job: "Paper Pusher"
            },
            {
                name: "Samir",
                job: "Programmer"
            }
        ],
        "ReynholmIndustries": [
            {
                name: "Moss",
                job: "Tech Support"
            }
        ]
    }
}

Middleware

In order to accept request bodies, we will need middleware. Specifically, a shim called body-parser, which interprets the body payload of a POST/PUT request and attaches it to the request object which our routes respond to.

bodyExample.js
var express = require('express'),
	app = express(),
	bodyParser = require('body-parser');

app.use(bodyParser.json());

app.post('/', function(req, res) {
	if (req.body.name) {
		console.log(req.body.name);
		console.table(req.body);
		res.status(204);
	} else {
		res.status(400);
	}
	res.end();
});

app.listen(8080, function() {
	console.log("Listening on 8080");
});