From 50dadb734015dcf6ca44ff4e1809ff5f453c6cb5 Mon Sep 17 00:00:00 2001 From: tactonbishop Date: Tue, 30 Aug 2022 10:00:04 +0100 Subject: [PATCH] Last Sync: 2022-08-30 10:00:04 --- .config/markdown-styles.css | 3 + .../REST_APIs/05_ Integrating_the_database.md | 10 ---- .../REST_APIs/05__Integrating_the_database.md | 10 ++++ .../NodeJS/REST_APIs/0_Introduction.md | 22 +++---- .../NodeJS/REST_APIs/1_GET.md | 18 +++--- .../NodeJS/REST_APIs/2_POST.md | 17 +++--- .../NodeJS/REST_APIs/3_PUT.md | 16 ++--- .../NodeJS/REST_APIs/4_DELETE.md | 7 ++- .../NodeJS/REST_APIs/Full_example.md | 58 +++++++++++-------- .../NodeJS/REST_APIs/Validation.md | 34 +++++------ markdown-styles.css | 11 ---- 11 files changed, 104 insertions(+), 102 deletions(-) create mode 100644 .config/markdown-styles.css delete mode 100644 Programming_Languages/NodeJS/REST_APIs/05_ Integrating_the_database.md create mode 100644 Programming_Languages/NodeJS/REST_APIs/05__Integrating_the_database.md delete mode 100644 markdown-styles.css diff --git a/.config/markdown-styles.css b/.config/markdown-styles.css new file mode 100644 index 0000000..e8205bd --- /dev/null +++ b/.config/markdown-styles.css @@ -0,0 +1,3 @@ +h1, h2, h3, h4, h5, h6, p { + font-family: 'Inter'; +} diff --git a/Programming_Languages/NodeJS/REST_APIs/05_ Integrating_the_database.md b/Programming_Languages/NodeJS/REST_APIs/05_ Integrating_the_database.md deleted file mode 100644 index 3105d5f..0000000 --- a/Programming_Languages/NodeJS/REST_APIs/05_ Integrating_the_database.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -categories: - - Programming Languages - - Databases -tags: [backend, node-js, REST, APIs, mongo-db] ---- - -# RESTful API with Node, Express and MongoDB: Integrating the database - -So far we have set up the application and a `/api/courses` route which handles requests for RESTful API operations on an array of course objects. We now want to have the endpoints operate on a MongoDB `courses` collection rather than the array. diff --git a/Programming_Languages/NodeJS/REST_APIs/05__Integrating_the_database.md b/Programming_Languages/NodeJS/REST_APIs/05__Integrating_the_database.md new file mode 100644 index 0000000..ffc2d00 --- /dev/null +++ b/Programming_Languages/NodeJS/REST_APIs/05__Integrating_the_database.md @@ -0,0 +1,10 @@ +--- +categories: + - Programming Languages + - Databases +tags: [backend, node-js, REST, APIs, mongo-db] +--- + +# Creating a RESTful API: Integrating the database + +So far we have set up the application and an `/api/courses` route which handles requests for RESTful API operations on a local array of course objects. We now want to have the endpoints operate on a MongoDB `courses` collection rather than the array. diff --git a/Programming_Languages/NodeJS/REST_APIs/0_Introduction.md b/Programming_Languages/NodeJS/REST_APIs/0_Introduction.md index ef82fd3..2b6204c 100644 --- a/Programming_Languages/NodeJS/REST_APIs/0_Introduction.md +++ b/Programming_Languages/NodeJS/REST_APIs/0_Introduction.md @@ -4,7 +4,7 @@ categories: tags: [backend, node-js, REST, APIs] --- -# RESTful API with Node, Express and MongoDB: Introduction +# Creating a RESTful API: Introduction We are going to use Express to create a [RESTful API](/Databases/RESTful_APIs.md) in Node.js. @@ -27,15 +27,15 @@ We will mainly work with the following array of objects: const courses = [ { id: 1, - name: 'First course', + name: "First course", }, { id: 2, - name: 'Second course', + name: "Second course", }, { id: 3, - name: 'Third course', + name: "Third course", }, ]; ``` @@ -45,19 +45,19 @@ const courses = [ We first create an instance of Express within `index.js`. This will be the main coordinating file and we will aim to minimise the amount of business logic we have in this file. It should really just be for initialization and managing [middleware](/Programming_Languages/NodeJS/Architecture/Middleware.md). ```js -const express = require('express'); +const express = require("express"); const app = express(); ``` ## Routing -We are going to receive all our HTTP requests at the path `/api/courses` and we will place all code related to this route in a dedicated Node module (`routes/courses.js`). +We are going to receive all our HTTP requests at the path `/api/courses` and we will place all code related to this route in a dedicated Node module (`routes/courses.js`) rather than within `index.js` which should remain as uncluttered as possible. First we need to declare this in `index.js`: ```js -const courses = require('./routes/courses'); -app.use('/api/courses', courses); +const courses = require("./routes/courses"); +app.use("/api/courses", courses); ``` Then within `courses.js` we instantiate an express router that `app.js` will route to: @@ -69,7 +69,7 @@ const router = express.Router(); Our REST requests will all follow the following pattern: ```js -router.get('/', (req, res) => { +router.get("/", (req, res) => { res.send(courses); }); ``` @@ -78,10 +78,10 @@ We target the `Router` instance we created and all paths will be expressed as `/ ## Create listener -With the routes setup and the Express instance created we can now listen for requests: +With the routing established and the Express instance created we can now listen for requests: ```js -app.listen(3000, () => console.log('Listening on port 30000...')); +app.listen(3000, () => console.log("Listening on port 30000...")); ``` ## REST endpoints diff --git a/Programming_Languages/NodeJS/REST_APIs/1_GET.md b/Programming_Languages/NodeJS/REST_APIs/1_GET.md index 6a3916d..fc8a827 100644 --- a/Programming_Languages/NodeJS/REST_APIs/1_GET.md +++ b/Programming_Languages/NodeJS/REST_APIs/1_GET.md @@ -4,7 +4,7 @@ categories: tags: [backend, node-js, REST, APIs] --- -# RESTful API with Node, Express and MongoDB: `GET` requests +# Creating a RESTful API: `GET` requests With our GET request we will simply return the array of course objects. @@ -12,7 +12,7 @@ We create an [event emitter](Events%20module.md#event-emitters) and listener tha ```js // Return a value as response from specified URI -router.get('/', (req, res) => { +router.get("/", (req, res) => { res.send(courses); }); ``` @@ -28,7 +28,7 @@ We can now call the endpoint: ```js const getAllCourses = async () => { try { - const resp = await axios.get('http://localhost:3000/api/courses'); + const resp = await axios.get("http://localhost:3000/api/courses"); console.log(resp.data); } catch (err) { console.error(err); @@ -42,9 +42,9 @@ Returns: ```js [ - {id: 1, name: 'First course'}, - {id: 2, name: 'Second course'}, - {id: 3, name: 'Third course'}, + { id: 1, name: "First course" }, + { id: 2, name: "Second course" }, + { id: 3, name: "Third course" }, ]; ``` @@ -53,7 +53,7 @@ Returns: The previous example serves the entire set of our data. But we will also need to retrieve specific values, we do this by adapting the GET callback to accept parameters. These parameters will correspond to the specific entry in our main data array. ```js -router.get('/:id', (req, res) => { +router.get("/:id", (req, res) => { res.send(req.params.id); }); ``` @@ -63,9 +63,9 @@ We use the `:` symbol in the URI to indicate that we looking to parse for a spec The block above is the most basic format but we would want to add some kind of error handling, for example: ```js -router.get('/:id', (req, res) => { +router.get("/:id", (req, res) => { const course = courses.find((c) => c.id === parseInt(req.params.id)); - if (!course) res.status(404).send('A course with the given ID was not found'); + if (!course) res.status(404).send("A course with the given ID was not found"); res.send(course); }); ``` diff --git a/Programming_Languages/NodeJS/REST_APIs/2_POST.md b/Programming_Languages/NodeJS/REST_APIs/2_POST.md index 1cc2a8e..74ba65a 100644 --- a/Programming_Languages/NodeJS/REST_APIs/2_POST.md +++ b/Programming_Languages/NodeJS/REST_APIs/2_POST.md @@ -4,12 +4,12 @@ categories: tags: [backend, node-js, REST, APIs] --- -# RESTful API with Node, Express and MongoDB: `POST` requests +# Creating a RESTful API: `POST` requests To demonstrate the handling of POST requests, we will create a handler that add a new element to the array of courses. ```js -router.post('/', (req, res) => { +router.post("/", (req, res) => { const course = { id: courses.length + 1, name: req.body.name, @@ -32,7 +32,7 @@ To execute the PUT request from the frontend: ```js const addCourse = async (newCourse) => { try { - const resp = await axios.post('http://localhost:3000/api/courses', { + const resp = await axios.post("http://localhost:3000/api/courses", { name: newCourse, }); console.log(resp.data); @@ -40,7 +40,7 @@ const addCourse = async (newCourse) => { console.error(err); } }; -addCourse('Biology and Life Sciences'); +addCourse("Biology and Life Sciences"); ``` Which returns: @@ -61,7 +61,7 @@ function validateCourse(course) { name: Joi.string().min(3).required(), }); - const {error} = schema.validate(course); + const { error } = schema.validate(course); return error; } ``` @@ -69,13 +69,14 @@ function validateCourse(course) { We can then add the validation as part of our general error handling: ```js -router.post('/', (req, res) => { +router.post("/", (req, res) => { const course = { id: courses.length + 1, name: req.body.name, }; - const {error} = schema.validate(req.body); - if (error) return error.details.map((joiErr) => res.status(400).send(joiErr.message)); + const { error } = schema.validate(req.body); + if (error) + return error.details.map((joiErr) => res.status(400).send(joiErr.message)); courses.push(course); res.send(course); diff --git a/Programming_Languages/NodeJS/REST_APIs/3_PUT.md b/Programming_Languages/NodeJS/REST_APIs/3_PUT.md index 9bff156..86a8c80 100644 --- a/Programming_Languages/NodeJS/REST_APIs/3_PUT.md +++ b/Programming_Languages/NodeJS/REST_APIs/3_PUT.md @@ -4,18 +4,20 @@ categories: tags: [backend, node-js, REST, APIs] --- -# RESTful API with Node, Express and MongoDB: `PUT` requests +# Creating a RESTful API: `PUT` requests To demonstrate the handling of PUT requests, we will create a handler that updates an element in the course array, based on its `id` and return the updated entry: ```js -router.put('/:id', (req, res) => { +router.put("/:id", (req, res) => { const course = courses.find((c) => c.id === parseInt(req.params.id)); - if (!course) return res.status(404).send('A course with the given ID was not found'); - const {error} = validateCourse(req.body); + if (!course) + return res.status(404).send("A course with the given ID was not found"); + const { error } = validateCourse(req.body); - if (error) return error.details.map((joiErr) => res.status(400).send(joiErr.message)); + if (error) + return error.details.map((joiErr) => res.status(400).send(joiErr.message)); course.name = req.body.name; res.send(course); @@ -27,7 +29,7 @@ Our request: ```js const updateCourse = async (courseChange) => { try { - const resp = await axios.put('http://localhost:3000/api/courses/1', { + const resp = await axios.put("http://localhost:3000/api/courses/1", { name: courseChange.name, }); console.log(resp.data); @@ -36,7 +38,7 @@ const updateCourse = async (courseChange) => { } }; -updateCourse({name: 'A new course'}); +updateCourse({ name: "A new course" }); ``` Returns: diff --git a/Programming_Languages/NodeJS/REST_APIs/4_DELETE.md b/Programming_Languages/NodeJS/REST_APIs/4_DELETE.md index fb95c78..4f0ec73 100644 --- a/Programming_Languages/NodeJS/REST_APIs/4_DELETE.md +++ b/Programming_Languages/NodeJS/REST_APIs/4_DELETE.md @@ -4,12 +4,13 @@ categories: tags: [backend, node-js, REST, APIs] --- -# RESTful API with Node, Express and MongoDB: `DELETE` requests +# Creating a RESTful API: `DELETE` requests ```js -router.delete('/:id', (req, res) => { +router.delete("/:id", (req, res) => { const course = courses.find((c) => c.id === parseInt(req.params.id)); - if (!course) return res.status(404).send('A course with the given ID was not found'); + if (!course) + return res.status(404).send("A course with the given ID was not found"); courses.indexOf(course); courses.splice(index, 1); diff --git a/Programming_Languages/NodeJS/REST_APIs/Full_example.md b/Programming_Languages/NodeJS/REST_APIs/Full_example.md index da553cc..4b9d339 100644 --- a/Programming_Languages/NodeJS/REST_APIs/Full_example.md +++ b/Programming_Languages/NodeJS/REST_APIs/Full_example.md @@ -4,19 +4,19 @@ categories: tags: [backend, node-js, REST, APIs] --- -# Full example +# Creating a RESTful API: Full example ```js -const express = require('express'); +const express = require("express"); const app = express(); // convention to name Express as the app const port = process.env.PORT || 3000; -const Joi = require('joi'); -const helmet = require('helmet'); -const morgan = require('morgan'); -const courses = require('./routes/courses'); +const Joi = require("joi"); +const helmet = require("helmet"); +const morgan = require("morgan"); +const courses = require("./routes/courses"); // Routes -app.use('/api/courses', courses); +app.use("/api/courses", courses); // Middlewear app.use(express.json()); @@ -25,20 +25,20 @@ app.use(helmet()); const courses = [ { id: 1, - name: 'First course', + name: "First course", }, { id: 2, - name: 'Second course', + name: "Second course", }, { id: 3, - name: 'Third course', + name: "Third course", }, ]; -if (app.get('env') === 'development') { - app.use(morgan('common')); +if (app.get("env") === "development") { + app.use(morgan("common")); } app.listen(port, () => console.log(`Listening on ${port}`)); @@ -48,30 +48,35 @@ function validateCourse(course) { name: Joi.string().min(3).required(), }); - const {error} = schema.validate(course); + const { error } = schema.validate(course); return error; } +/** + * Note that the following request handlers would not be stored in `index.js` they would be in their dedicated routing file. + **/ + // Return all data from API -courses.get('/', (req, res) => { +courses.get("/", (req, res) => { res.send(courses); }); // Return a specific value -courses.get('/:id', (req, res) => { +courses.get("/:id", (req, res) => { const course = courses.find((c) => c.id === parseInt(req.params.id)); - if (!course) res.status(404).send('A course with the given ID was not found'); + if (!course) res.status(404).send("A course with the given ID was not found"); res.send(course); }); // Add a new course -courses.post('/', (req, res) => { +courses.post("/", (req, res) => { const schema = Joi.object({ name: Joi.string().min(3).required(), }); - const {error} = schema.validate(req.body); - if (error) return error.details.map((joiErr) => res.status(400).send(joiErr.message)); + const { error } = schema.validate(req.body); + if (error) + return error.details.map((joiErr) => res.status(400).send(joiErr.message)); const course = { id: courses.length + 1, @@ -82,22 +87,25 @@ courses.post('/', (req, res) => { }); // Update a course -courses.put('/:id', (req, res) => { +courses.put("/:id", (req, res) => { const course = courses.find((c) => c.id === parseInt(req.params.id)); - if (!course) return res.status(404).send('A course with the given ID was not found'); - const {error} = validateCourse(req.body); + if (!course) + return res.status(404).send("A course with the given ID was not found"); + const { error } = validateCourse(req.body); - if (error) return error.details.map((joiErr) => res.status(400).send(joiErr.message)); + if (error) + return error.details.map((joiErr) => res.status(400).send(joiErr.message)); course.name = req.body.name; res.send(course); }); // Delete a course -courses.delete('/:id', (req, res) => { +courses.delete("/:id", (req, res) => { const course = courses.find((c) => c.id === parseInt(req.params.id)); - if (!course) return res.status(404).send('A course with the given ID was not found'); + if (!course) + return res.status(404).send("A course with the given ID was not found"); courses.indexOf(course); courses.splice(index, 1); diff --git a/Programming_Languages/NodeJS/REST_APIs/Validation.md b/Programming_Languages/NodeJS/REST_APIs/Validation.md index 705541d..5b24e9f 100644 --- a/Programming_Languages/NodeJS/REST_APIs/Validation.md +++ b/Programming_Languages/NodeJS/REST_APIs/Validation.md @@ -1,12 +1,12 @@ --- -tags: - - Programming_Languages - - backend - - node-js - - validation +categories: + - Programming Languages +tags: [backend, node-js, REST, APIs, validation] --- -We can provide server-side validation for our projects by using a **schema validator**. This is a program that declaratively parses the JSON values received as requests from the client. This makes it easy to systematically validate the data that we receive from any HTTP requests where the client sends a body to the endpoint. +# Creating a RESTful API: Validation + +We can provide server-side validation for our projects by using a **schema validator**. This is a program that declaratively parses the JSON values received as requests from the client. This makes it easy to systematically validate the data that we receive from any HTTP requests where the client sends a body to the endpoint. One of the most popular schema validators for NodeJS is [joi](https://www.npmjs.com/package/joi). @@ -15,24 +15,22 @@ One of the most popular schema validators for NodeJS is [joi](https://www.npmjs. Let's say we have a POST request that expects a single field as the body that must be a string and greater than two characters long. First we define our schema: ```js - const schema = Joi.object({ - name: Joi.string().min(3).required(), - }); - - const { error } = schema.validate(req.body); +const schema = Joi.object({ + name: Joi.string().min(3).required(), +}); +const { error } = schema.validate(req.body); ``` -The `schema` variable is an object whose keys should match those of the intended request body. Instead of actual values we provide Joi's in-built validators, concatenated as necessary. We then store the results of the validation in a variable. +The `schema` variable is an object whose keys should match those of the intended request body. Instead of actual values we provide Joi's in-built validators, concatenated as necessary. We then store the results of the validation in a variable. Next we add handling in the case of errors: -````js +```js if (error) { - error.details.map((joiErr) => res.status(400).send(joiErr.message)); - return; - } - -```` + error.details.map((joiErr) => res.status(400).send(joiErr.message)); + return; +} +``` We loop through the error array and return 400s as the response if they are found. If there are no errors, the Joi object will return `undefined`. diff --git a/markdown-styles.css b/markdown-styles.css deleted file mode 100644 index 35814d8..0000000 --- a/markdown-styles.css +++ /dev/null @@ -1,11 +0,0 @@ -* { - font-family: 'Inter'; -} - -pre, code { - font-family: 'Liga Liberation Mono' !important; -} - -code { - font-family: 'Liga Liberation Mono' !important; -} \ No newline at end of file