├── .gitignore ├── public ├── text │ └── data.txt ├── img │ └── img1.jpg └── css │ └── style.css ├── model └── employees.json ├── middleware ├── errorHandler.js └── logEvents.js ├── views ├── subdir │ ├── test.html │ └── index.html ├── 404.html ├── index.html └── new-page.html ├── routes ├── subdir.js ├── root.js └── api │ └── employees.js ├── package.json ├── README.md ├── server.js └── logs └── reqLog.txt /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /public/text/data.txt: -------------------------------------------------------------------------------- 1 | Just some random text. -------------------------------------------------------------------------------- /public/img/img1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitdagray/express_routers/HEAD/public/img/img1.jpg -------------------------------------------------------------------------------- /model/employees.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "firstname": "Dave", 5 | "lastname": "Gray" 6 | }, 7 | { 8 | "id": 2, 9 | "firstname": "John", 10 | "lastname": "Smith" 11 | } 12 | ] -------------------------------------------------------------------------------- /public/css/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | font-size: 36px; 9 | min-height: 100vh; 10 | color: #fff; 11 | background-color: #000; 12 | display: grid; 13 | place-content: center; 14 | } 15 | -------------------------------------------------------------------------------- /middleware/errorHandler.js: -------------------------------------------------------------------------------- 1 | const { logEvents } = require('./logEvents'); 2 | 3 | const errorHandler = (err, req, res, next) => { 4 | logEvents(`${err.name}: ${err.message}`, 'errLog.txt'); 5 | console.error(err.stack) 6 | res.status(500).send(err.message); 7 | } 8 | 9 | module.exports = errorHandler; -------------------------------------------------------------------------------- /views/subdir/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Test Page 9 | 10 | 11 | 12 |

Test Page in /subdir/

13 | 14 | 15 | -------------------------------------------------------------------------------- /views/subdir/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Subdirectory Index 9 | 10 | 11 | 12 |

Subdirectory Index

13 | 14 | 15 | -------------------------------------------------------------------------------- /views/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 404 9 | 10 | 11 | 12 | 13 |

404

14 | 15 | 16 | -------------------------------------------------------------------------------- /views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Index 9 | 10 | 11 | 12 | 13 |

Index

14 | 15 | 16 | -------------------------------------------------------------------------------- /routes/subdir.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const path = require('path'); 4 | 5 | router.get('^/$|/index(.html)?', (req, res) => { 6 | res.sendFile(path.join(__dirname, '..', 'views', 'subdir', 'index.html')); 7 | }); 8 | 9 | router.get('/test(.html)?', (req, res) => { 10 | res.sendFile(path.join(__dirname, '..', 'views', 'subdir', 'test.html')); 11 | }); 12 | 13 | module.exports = router; -------------------------------------------------------------------------------- /views/new-page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | New Page 9 | 10 | 11 | 12 | 13 |

New Page

14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "08tut", 3 | "version": "1.0.0", 4 | "description": "Express tutorial", 5 | "main": "server.js", 6 | "scripts": { 7 | "start": "node server", 8 | "dev": "nodemon server" 9 | }, 10 | "author": "Dave Gray", 11 | "license": "ISC", 12 | "dependencies": { 13 | "cors": "^2.8.5", 14 | "date-fns": "^2.23.0", 15 | "express": "^4.17.1", 16 | "uuid": "^8.3.2" 17 | }, 18 | "devDependencies": { 19 | "nodemon": "^2.0.12" 20 | } 21 | } -------------------------------------------------------------------------------- /routes/root.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const path = require('path'); 4 | 5 | router.get('^/$|/index(.html)?', (req, res) => { 6 | res.sendFile(path.join(__dirname, '..', 'views', 'index.html')); 7 | }); 8 | 9 | router.get('/new-page(.html)?', (req, res) => { 10 | res.sendFile(path.join(__dirname, '..', 'views', 'new-page.html')); 11 | }); 12 | 13 | router.get('/old-page(.html)?', (req, res) => { 14 | res.redirect(301, '/new-page.html'); //302 by default 15 | }); 16 | 17 | module.exports = router; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # "Express JS Tutorial - Routers" 2 | 3 | ✅ [Check out my YouTube Channel with all of my tutorials](https://www.youtube.com/DaveGrayTeachesCode). 4 | 5 | **Description:** 6 | 7 | This repository shares the code applied during the Youtube tutorial. The tutorial is part of a [Node.js & Express for Beginners Playlist](https://www.youtube.com/playlist?list=PL0Zuz27SZ-6PFkIxaJ6Xx_X46avTM1aYw) on my channel. 8 | 9 | [YouTube Tutorial](https://youtu.be/Zh7psmf1KAA) for this repository. 10 | 11 | I suggest completing my [8 hour JavaScript course tutorial video](https://youtu.be/EfAl9bwzVZk) if you are new to Javascript. 12 | 13 | ### Academic Honesty 14 | 15 | **DO NOT COPY FOR AN ASSIGNMENT** - Avoid plagiargism and adhere to the spirit of this [Academic Honesty Policy](https://www.freecodecamp.org/news/academic-honesty-policy/). 16 | -------------------------------------------------------------------------------- /routes/api/employees.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const data = {}; 4 | data.employees = require('../../data/employees.json'); 5 | 6 | router.route('/') 7 | .get((req, res) => { 8 | res.json(data.employees); 9 | }) 10 | .post((req, res) => { 11 | res.json({ 12 | "firstname": req.body.firstname, 13 | "lastname": req.body.lastname 14 | }); 15 | }) 16 | .put((req, res) => { 17 | res.json({ 18 | "firstname": req.body.firstname, 19 | "lastname": req.body.lastname 20 | }); 21 | }) 22 | .delete((req, res) => { 23 | res.json({ "id": req.body.id }) 24 | }); 25 | 26 | router.route('/:id') 27 | .get((req, res) => { 28 | res.json({ "id": req.params.id }); 29 | }); 30 | 31 | module.exports = router; -------------------------------------------------------------------------------- /middleware/logEvents.js: -------------------------------------------------------------------------------- 1 | const { format } = require('date-fns'); 2 | const { v4: uuid } = require('uuid'); 3 | 4 | const fs = require('fs'); 5 | const fsPromises = require('fs').promises; 6 | const path = require('path'); 7 | 8 | const logEvents = async (message, logName) => { 9 | const dateTime = `${format(new Date(), 'yyyyMMdd\tHH:mm:ss')}`; 10 | const logItem = `${dateTime}\t${uuid()}\t${message}\n`; 11 | 12 | try { 13 | if (!fs.existsSync(path.join(__dirname, '..', 'logs'))) { 14 | await fsPromises.mkdir(path.join(__dirname, '..', 'logs')); 15 | } 16 | 17 | await fsPromises.appendFile(path.join(__dirname, '..', 'logs', logName), logItem); 18 | } catch (err) { 19 | console.log(err); 20 | } 21 | } 22 | 23 | const logger = (req, res, next) => { 24 | logEvents(`${req.method}\t${req.headers.origin}\t${req.url}`, 'reqLog.txt'); 25 | console.log(`${req.method} ${req.path}`); 26 | next(); 27 | } 28 | 29 | module.exports = { logger, logEvents }; 30 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const path = require('path'); 4 | const cors = require('cors'); 5 | const { logger } = require('./middleware/logEvents'); 6 | const errorHandler = require('./middleware/errorHandler'); 7 | const PORT = process.env.PORT || 3500; 8 | 9 | // custom middleware logger 10 | app.use(logger); 11 | 12 | // Cross Origin Resource Sharing 13 | const whitelist = ['https://www.yoursite.com', 'http://127.0.0.1:5500', 'http://localhost:3500']; 14 | const corsOptions = { 15 | origin: (origin, callback) => { 16 | if (whitelist.indexOf(origin) !== -1 || !origin) { 17 | callback(null, true) 18 | } else { 19 | callback(new Error('Not allowed by CORS')); 20 | } 21 | }, 22 | optionsSuccessStatus: 200 23 | } 24 | app.use(cors(corsOptions)); 25 | 26 | // built-in middleware to handle urlencoded data 27 | // in other words, form data: 28 | // ‘content-type: application/x-www-form-urlencoded’ 29 | app.use(express.urlencoded({ extended: false })); 30 | 31 | // built-in middleware for json 32 | app.use(express.json()); 33 | 34 | //serve static files 35 | app.use('/', express.static(path.join(__dirname, '/public'))); 36 | app.use('/subdir', express.static(path.join(__dirname, '/public'))); 37 | 38 | // routes 39 | app.use('/', require('./routes/root')); 40 | app.use('/subdir', require('./routes/subdir')); 41 | app.use('/employees', require('./routes/api/employees')); 42 | 43 | app.all('*', (req, res) => { 44 | res.status(404); 45 | if (req.accepts('html')) { 46 | res.sendFile(path.join(__dirname, 'views', '404.html')); 47 | } else if (req.accepts('json')) { 48 | res.json({ "error": "404 Not Found" }); 49 | } else { 50 | res.type('txt').send("404 Not Found"); 51 | } 52 | }); 53 | 54 | app.use(errorHandler); 55 | 56 | app.listen(PORT, () => console.log(`Server running on port ${PORT}`)); -------------------------------------------------------------------------------- /logs/reqLog.txt: -------------------------------------------------------------------------------- 1 | 20210919 14:08:36 be8a4af7-d187-460c-b419-5063434bdf87 GET undefined / 2 | 20210919 14:08:36 6d664cd6-5d41-45f6-8e24-cbd841f3ff08 GET undefined /css/style.css 3 | 20210919 14:08:45 064bcc18-2a57-42c3-977b-968e1acdb2f6 GET undefined /subdir 4 | 20210919 14:09:07 33739abb-d102-4a90-b173-269f46702886 GET undefined /subdir/test.html 5 | 20210919 14:09:46 7f19e6e9-910d-446e-8280-cb6ab7a0633a GET undefined /subdir/dave 6 | 20210919 14:09:46 54feeaea-997a-4b83-b381-7171f770014a GET undefined /subdir/css/style.css 7 | 20210919 14:10:09 a6ca02b3-979d-41bb-b2b0-cbc503ae4179 GET undefined /dave 8 | 20210919 14:10:09 ace741a1-7342-4707-bdf6-4746c0883062 GET undefined /css/style.css 9 | 20210919 14:11:15 9a4eab31-d6e3-4fcf-b7b4-db3e602d4872 GET undefined /subdir/dave 10 | 20210919 14:11:15 6718115b-a4ff-4391-8949-4db5af99e6b6 GET undefined /subdir/css/style.css 11 | 20210919 14:11:25 c3588814-3774-4dd7-8c03-78a3e5264319 GET undefined /subdir/dave 12 | 20210919 14:11:25 39c460d2-7d5c-41c0-b4ae-dfcd1f92265b GET undefined /subdir/css/style.css 13 | 20210919 14:15:55 c77ac7af-89ed-4481-b688-77962b4af28d GET undefined / 14 | 20210919 14:15:55 d4209ed2-186c-4c5b-9899-334a1753fae3 GET undefined /css/style.css 15 | 20210919 14:16:01 97da2591-45a5-441b-9125-297477bc8cc3 GET undefined /new-page 16 | 20210919 14:16:01 d6297629-dc0f-42f5-8800-f4e4a0c3ac42 GET undefined /img/img1.jpg 17 | 20210919 14:16:01 155f0792-e597-4cbb-829d-4945e75469e4 GET undefined /css/style.css 18 | 20210919 14:16:17 81dfc877-f720-4bee-b398-f9f388967fd7 GET undefined /old-page 19 | 20210919 14:16:17 afa318e9-e722-4bdd-90d9-3b62700f909f GET undefined /new-page.html 20 | 20210919 14:16:17 fba8e0f9-5c06-44cd-b831-80b1666d72ac GET undefined /css/style.css 21 | 20210919 14:16:17 c78cb5ba-2f07-4d45-9506-6b31769a84c6 GET undefined /img/img1.jpg 22 | 20210919 14:16:23 00e0b3ca-3605-4217-b9a9-a44496014fda GET undefined /index 23 | 20210919 14:16:23 9d9ebeeb-8433-4304-97c1-caa300a49ee4 GET undefined /css/style.css 24 | 20210919 14:35:11 bbb68c55-e293-42a6-9c69-7ccee00a78a4 GET undefined /employees 25 | 20210919 14:35:51 782ddc31-f832-49b6-b594-cf9ef9d1a701 POST undefined /employees 26 | 20210919 14:36:33 c3689027-d6e0-44d5-ab49-a2da4deb3a64 PUT undefined /employees 27 | 20210919 14:36:53 86f56842-518f-44d2-b790-08a2d09d9727 DELETE undefined /employees 28 | 20210919 14:37:21 271bf802-e8f9-4ccd-ab4a-5e37b052bde1 GET undefined /employees/1 29 | --------------------------------------------------------------------------------