├── .babelrc ├── .env ├── .github └── FUNDING.yml ├── .gitignore ├── .prettierrc ├── .travis.yml ├── README.md ├── package-lock.json ├── package.json └── src ├── index.js ├── models └── index.js └── routes ├── index.js ├── message.js ├── session.js └── user.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env" 4 | ] 5 | } -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | PORT=3000 -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: rwieruch 4 | patreon: # rwieruch 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with a single custom sponsorship URL 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logfile 2 | 3 | node_modules/ -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "all", 4 | "singleQuote": true, 5 | "printWidth": 70, 6 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - stable 5 | 6 | install: 7 | - npm install 8 | 9 | script: 10 | - npm test 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple Node with Express Server with REST API 2 | 3 | [![Build Status](https://travis-ci.org/rwieruch/node-express-server-rest-api.svg?branch=master)](https://travis-ci.org/rwieruch/node-express-server-rest-api) [![Slack](https://slack-the-road-to-learn-react.wieruch.com/badge.svg)](https://slack-the-road-to-learn-react.wieruch.com/) [![Greenkeeper badge](https://badges.greenkeeper.io/rwieruch/node-express-server-rest-api.svg)](https://greenkeeper.io/) 4 | 5 | An easy way to get started with a Express server offering a REST API with Node.js. [Read more about it.](https://www.robinwieruch.de/node-express-server-rest-api) 6 | 7 | ## Features 8 | 9 | - Express 10 | - REST API 11 | 12 | ## Requirements 13 | 14 | - [node & npm](https://nodejs.org/en/) 15 | - [git](https://www.robinwieruch.de/git-essential-commands/) 16 | 17 | ## Installation 18 | 19 | - `git clone git@github.com:rwieruch/node-express-server-rest-api.git` 20 | - `cd node-express-server-rest-api` 21 | - `npm install` 22 | - `npm start` 23 | - optional: include _.env_ in your _.gitignore_ 24 | 25 | ### GET Routes 26 | 27 | - visit http://localhost:3000 28 | - /messages 29 | - /messages/1 30 | - /users 31 | - /users/1 32 | 33 | ### Beyond GET Routes 34 | 35 | #### CURL 36 | 37 | - Create a message with: 38 | - `curl -X POST -H "Content-Type:application/json" http://localhost:3000/messages -d '{"text":"Hi again, World"}'` 39 | - Delete a message with: 40 | - `curl -X DELETE -H "Content-Type:application/json" http://localhost:3000/messages/1` 41 | 42 | #### Postman 43 | 44 | - Install [Postman](https://www.getpostman.com/apps) to interact with REST API 45 | - Create a message with: 46 | - URL: http://localhost:3000/messages 47 | - Method: POST 48 | - Body: raw + JSON (application/json) 49 | - Body Content: `{ "text": "Hi again, World" }` 50 | - Delete a message with: 51 | - URL: http://localhost:3000/messages/1 52 | - Method: DELETE 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-express-server-rest-api", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon --exec babel-node src/index.js", 8 | "test": "echo \"No test specified\" && exit 0" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "@babel/core": "^7.17.5", 15 | "@babel/node": "^7.16.8", 16 | "@babel/preset-env": "^7.16.11", 17 | "nodemon": "^2.0.15" 18 | }, 19 | "dependencies": { 20 | "cors": "^2.8.5", 21 | "dotenv": "^16.0.0", 22 | "express": "^4.17.3", 23 | "uuid": "^8.3.2" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import 'dotenv/config'; 2 | import cors from 'cors'; 3 | import express from 'express'; 4 | 5 | import models from './models'; 6 | import routes from './routes'; 7 | 8 | const app = express(); 9 | 10 | // * Application-Level Middleware * // 11 | 12 | // Third-Party Middleware 13 | 14 | app.use(cors()); 15 | 16 | // Built-In Middleware 17 | 18 | app.use(express.json()); 19 | app.use(express.urlencoded({ extended: true })); 20 | 21 | // Custom Middleware 22 | 23 | app.use((req, res, next) => { 24 | req.context = { 25 | models, 26 | me: models.users[1], 27 | }; 28 | next(); 29 | }); 30 | 31 | // * Routes * // 32 | 33 | app.use('/session', routes.session); 34 | app.use('/users', routes.user); 35 | app.use('/messages', routes.message); 36 | 37 | // * Start * // 38 | 39 | app.listen(process.env.PORT, () => 40 | console.log(`Example app listening on port ${process.env.PORT}!`), 41 | ); 42 | -------------------------------------------------------------------------------- /src/models/index.js: -------------------------------------------------------------------------------- 1 | let users = { 2 | 1: { 3 | id: '1', 4 | username: 'Robin Wieruch', 5 | }, 6 | 2: { 7 | id: '2', 8 | username: 'Dave Davids', 9 | }, 10 | }; 11 | 12 | let messages = { 13 | 1: { 14 | id: '1', 15 | text: 'Hello World', 16 | userId: '1', 17 | }, 18 | 2: { 19 | id: '2', 20 | text: 'By World', 21 | userId: '2', 22 | }, 23 | }; 24 | 25 | export default { 26 | users, 27 | messages, 28 | }; 29 | -------------------------------------------------------------------------------- /src/routes/index.js: -------------------------------------------------------------------------------- 1 | import session from './session'; 2 | import user from './user'; 3 | import message from './message'; 4 | 5 | export default { 6 | session, 7 | user, 8 | message, 9 | }; 10 | -------------------------------------------------------------------------------- /src/routes/message.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuidv4 } from 'uuid'; 2 | import { Router } from 'express'; 3 | 4 | const router = Router(); 5 | 6 | router.get('/', (req, res) => { 7 | return res.send(Object.values(req.context.models.messages)); 8 | }); 9 | 10 | router.get('/:messageId', (req, res) => { 11 | return res.send(req.context.models.messages[req.params.messageId]); 12 | }); 13 | 14 | router.post('/', (req, res) => { 15 | const id = uuidv4(); 16 | const message = { 17 | id, 18 | text: req.body.text, 19 | userId: req.context.me.id, 20 | }; 21 | 22 | req.context.models.messages[id] = message; 23 | 24 | return res.send(message); 25 | }); 26 | 27 | router.delete('/:messageId', (req, res) => { 28 | const { 29 | [req.params.messageId]: message, 30 | ...otherMessages 31 | } = req.context.models.messages; 32 | 33 | req.context.models.messages = otherMessages; 34 | 35 | return res.send(message); 36 | }); 37 | 38 | router.put('/:messageId', (req, res) => { 39 | const { 40 | [req.params.messageId]: message 41 | } = req.context.models.messages; 42 | 43 | const updatedMessage = { 44 | ...message, 45 | text: req.body.text 46 | }; 47 | 48 | req.context.models.messages[req.params.messageId] = updatedMessage; 49 | 50 | return res.send(updatedMessage); 51 | }) 52 | 53 | export default router; 54 | -------------------------------------------------------------------------------- /src/routes/session.js: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | 3 | const router = Router(); 4 | 5 | router.get('/', (req, res) => { 6 | return res.send(req.context.models.users[req.context.me.id]); 7 | }); 8 | 9 | export default router; 10 | -------------------------------------------------------------------------------- /src/routes/user.js: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | 3 | const router = Router(); 4 | 5 | router.get('/', (req, res) => { 6 | return res.send(Object.values(req.context.models.users)); 7 | }); 8 | 9 | router.get('/:userId', (req, res) => { 10 | return res.send(req.context.models.users[req.params.userId]); 11 | }); 12 | 13 | export default router; 14 | --------------------------------------------------------------------------------