├── .gitignore ├── LICENSE ├── README.md ├── app.js ├── data.json ├── package.json ├── routes ├── cars │ ├── all.js │ ├── index.js │ └── single.js ├── index.js └── models │ ├── all.js │ ├── cars │ ├── all.js │ └── index.js │ ├── index.js │ └── single.js └── utils └── findObject.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Alex Sears 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # express-routing-example 2 | Example API built using Express routers 3 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | // Bring in our dependencies 2 | const app = require('express')(); 3 | const routes = require('./routes'); 4 | const PORT = process.env.PORT || 3000; 5 | 6 | // Connect all our routes to our application 7 | app.use('/', routes); 8 | 9 | // Turn on that server! 10 | app.listen(PORT, () => { 11 | console.log(`App listening on port ${PORT}`); 12 | }); 13 | -------------------------------------------------------------------------------- /data.json: -------------------------------------------------------------------------------- 1 | { 2 | "models": [ 3 | { 4 | "id": 1, 5 | "name": "Toyota" 6 | }, 7 | { 8 | "id": 2, 9 | "name": "Mazda" 10 | } 11 | ], 12 | "cars": [ 13 | { 14 | "id": 1, 15 | "name": "Corolla", 16 | "modelId": 1 17 | }, 18 | { 19 | "id": 2, 20 | "name": "Mazda3", 21 | "modelId": 2 22 | }, 23 | { 24 | "id": 3, 25 | "name": "Mazda6", 26 | "modelId": 2 27 | }, 28 | { 29 | "id": 4, 30 | "name": "Miata", 31 | "modelId": 2 32 | }, 33 | { 34 | "id": 5, 35 | "name": "Camry", 36 | "modelId": 1 37 | }, 38 | { 39 | "id": 6, 40 | "name": "CX-9", 41 | "modelId": 2 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-routing-example", 3 | "version": "1.0.0", 4 | "description": "Example API built using Express routers", 5 | "main": "index.js", 6 | "scripts": { 7 | "serve": "nodemon app.js", 8 | "start": "node app.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/searsaw/express-routing-example.git" 13 | }, 14 | "author": "Alex Sears", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/searsaw/express-routing-example/issues" 18 | }, 19 | "homepage": "https://github.com/searsaw/express-routing-example#readme", 20 | "dependencies": { 21 | "express": "^4.13.4" 22 | }, 23 | "devDependencies": { 24 | "eslint": "^2.4.0", 25 | "eslint-config-airbnb": "^6.1.0", 26 | "nodemon": "^1.9.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /routes/cars/all.js: -------------------------------------------------------------------------------- 1 | const data = require('../../data.json'); 2 | 3 | module.exports = (req, res) => { 4 | const cars = data.cars; 5 | 6 | res.status(200).json({ cars }); 7 | }; 8 | -------------------------------------------------------------------------------- /routes/cars/index.js: -------------------------------------------------------------------------------- 1 | const cars = require('express').Router(); 2 | const all = require('./all'); 3 | const single = require('./single'); 4 | const findObject = require('../../utils/findObject'); 5 | 6 | cars.param('carId', findObject('car')); 7 | 8 | cars.get('/', all); 9 | cars.get('/:carId', single); 10 | 11 | module.exports = cars; 12 | -------------------------------------------------------------------------------- /routes/cars/single.js: -------------------------------------------------------------------------------- 1 | module.exports = (req, res) => { 2 | const car = req.car; 3 | 4 | res.status(200).json({ car }); 5 | }; 6 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | const routes = require('express').Router(); 2 | const models = require('./models'); 3 | const cars = require('./cars'); 4 | 5 | routes.use('/models', models); 6 | routes.use('/cars', cars); 7 | 8 | routes.get('/', (req, res) => { 9 | res.status(200).json({ message: 'Connected!' }); 10 | }); 11 | 12 | module.exports = routes; 13 | -------------------------------------------------------------------------------- /routes/models/all.js: -------------------------------------------------------------------------------- 1 | const data = require('../../data.json'); 2 | 3 | module.exports = (req, res) => { 4 | const models = data.models; 5 | 6 | res.status(200).json({ models }); 7 | }; 8 | -------------------------------------------------------------------------------- /routes/models/cars/all.js: -------------------------------------------------------------------------------- 1 | const data = require('../../../data.json'); 2 | 3 | module.exports = (req, res) => { 4 | const modelId = req.params.modelId * 1; 5 | const cars = data.cars.filter(c => c.modelId === modelId); 6 | 7 | res.status(200).json({ cars }); 8 | }; 9 | -------------------------------------------------------------------------------- /routes/models/cars/index.js: -------------------------------------------------------------------------------- 1 | const cars = require('express').Router({ mergeParams: true }); 2 | const all = require('./all'); 3 | 4 | cars.get('/', all); 5 | 6 | module.exports = cars; 7 | -------------------------------------------------------------------------------- /routes/models/index.js: -------------------------------------------------------------------------------- 1 | const models = require('express').Router(); 2 | const all = require('./all'); 3 | const single = require('./single'); 4 | const cars = require('./cars'); 5 | const findObject = require('../../utils/findObject'); 6 | 7 | models.param('modelId', findObject('model')); 8 | 9 | models.use('/:modelId/cars', cars); 10 | 11 | models.get('/:modelId', single); 12 | models.get('/', all); 13 | 14 | module.exports = models; 15 | -------------------------------------------------------------------------------- /routes/models/single.js: -------------------------------------------------------------------------------- 1 | module.exports = (req, res) => { 2 | const model = req.model; 3 | 4 | res.status(200).json({ model }); 5 | }; 6 | -------------------------------------------------------------------------------- /utils/findObject.js: -------------------------------------------------------------------------------- 1 | /* eslint no-param-reassign: 0 */ 2 | const data = require('../data.json'); 3 | 4 | module.exports = type => { 5 | return (req, res, next, value) => { 6 | const typePlural = `${type}s`; 7 | const obj = data[typePlural].find(t => t.id === (value * 1)); 8 | 9 | if (obj) { 10 | req[type] = obj; 11 | next(); 12 | } else { 13 | res.status(404).send(`Invalid ${type} ID`); 14 | } 15 | }; 16 | }; 17 | --------------------------------------------------------------------------------