0% found this document useful (0 votes)
27 views14 pages

Express - Part-1

The document provides an overview of building RESTful APIs with Express including common HTTP methods, route parameters, handling requests, input validation, and other advanced topics like middleware, configuration, debugging and templating engines.

Uploaded by

gepiged536
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
27 views14 pages

Express - Part-1

The document provides an overview of building RESTful APIs with Express including common HTTP methods, route parameters, handling requests, input validation, and other advanced topics like middleware, configuration, debugging and templating engines.

Uploaded by

gepiged536
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Building RESTful APIs with Express

So, in this section, you learned that:

- REST(Representational State Transfer) defines a set of conventions for creating


HTTP services (CRUD operations):
- POST: to create a resource
- PUT: to update it
- GET: to read it
- DELETE: to delete it

- Express is a simple, minimalistic and lightweight framework for building web


servers.

Startup & installation


mkdir express-demo
npm init -y
npm i express

// Build a web server


const express = require(‘express’);
const app = express();

Ex 1:
const express = require("express");
const app = express();

/* http methods
app.get()
app.put()
app.post()
app.delete()
*/

app.get("/", (req, res) => {


// res.download('index.js') - to download a file from server

res.send("hello world");
});

app.get("/games/cricket", (req, res)=>{


res.send([1,2,3])
})

app.listen(3000, () => console.log("Listening on port 3000...."));


// Listen on port 3000
app.listen(3000, () => console.log(‘Listening…’));- We use Nodemon to watch for
changes in files and automatically restart the node process.

Nodemon – node monitor


npm i -g nodemon
nodemon index.js

// Reading the port from an environment variable


- We can use environment variables to store various settings for an application. To
read an environment variable, we use process.env.
const port = process.env.PORT || 3000;
app.listen(port);

const port = process.env.PORT || 3000;


app.listen(port, () => console.log(`Listening on port ${port}....`));

to set port on local machine: open cmd > set PORT=5000 > nodemon index.js

Route Parameters:
// ex: http://localhost:3000/api/courses/11
app.get("/api/courses/:id", (req, res) => {
res.send(req.params.id);
});

// ex: http://localhost:3000/api/courses/2018/feb
app.get("/api/courses/:year/:month", (req, res) => {
res.send(req.params); // params object
});

// ex: http://localhost:3000/api/courses?sortBy=name
app.get("/api/courses", (req, res) => {
res.send(req.query); // query string
});

app.get("/users", (req, res) => {


res.send(req.originalUrl);
});

// http://localhost:3000/users?name=decdier
app.get("/users", (req, res) => {
res.send(req.query.name);
});

Handling HTTP GET Request


const courses = [
{ id: 1, name: "course1" },
{ id: 2, name: "course2" },
{ id: 3, name: "course3" },
];
app.get("/api/courses", (req, res) => {
res.send(courses);
});

app.get("/api/courses/:id", (req, res) => {


const course = courses.find((c) => c.id === parseInt(req.params.id));
if (!course)
res.status(404).send("The course you are searching was not found");
res.send(course);
});

// Getting all the courses


app.get(‘/api/courses’, (req, res) => {
// To read query string parameters (?sortBy=name)
const sortBy = req.query.sortBy;
// Return the courses res.send(courses);
});

// Getting a single course


app.get(‘/api/courses/:id’, (req, res) => {
const courseId = req.params.id;
// Lookup the course
// If not found, return 404
res.status(404).send(‘Course not found.’);
// Else, return the course object
res.send(course);
});

Handling HTTP POST Request


// run postman => new => select post and paste url => body => raw => {"name": "new
course" } => then send
app.use(express.json()); // express.json() returns middleware and the app.use will
uses it
app.post("/api/courses", (req, res) => {
const course = {
id: courses.length + 1,
name: req.body.name,
};
courses.push(course);
res.send(courses);
});

// Creating a course
app.post(‘/api/courses’, (req, res) => {
// Create the course and return the course object
resn.send(course);
});
Input Validation
app.post("/api/courses", (req, res) => {
if (!req.body.name || req.body.name.length < 3) {
res.status(400).send("There was an error in the name property");
}
const course = {
id: courses.length + 1,
name: req.body.name,
};
courses.push(course);
res.send(courses);
});

Using joi package


- You should never trust data sent by the client. Always validate! Use Joi package
to perform input validation.
// npm i joi
const Joi = require("joi");
app.post("/api/courses", (req, res) => {
const schema = Joi.object({
name: Joi.string().min(3).required(),
});

const result = schema.validate(req.body);

if (result.error) {
res.status(400).send(result.error.details[0].message);
}

const course = {
id: courses.length + 1,
name: req.body.name,
};
courses.push(course);
res.send(courses);
});

Handling HTTP PUT Request


app.put("/api/courses/:id", (req, res) => {
const schema = Joi.object({
name: Joi.string().min(3).required(),
});

const { error } = schema.validate(req.body);

if (error) {
res.status(400).send(error.details[0].message);
return;
}

const course = courses.find((c) => c.id === parseInt(req.params.id));


if (!course) {
res.status(404).send("The course you are searching was not found");
}
course.name = req.body.name;
res.send(courses);
});

// Updating a course
app.put(‘/api/courses/:id’, (req, res) => {
// If course not found, return 404, otherwise update it
// and return the updated object.
});

Handling HTTP DELETE Request


app.delete("/api/courses/:id", (req, res) => {
const course = courses.find((c) => c.id === parseInt(req.params.id));
if (!course)
return res.status(404).send("The course you are searching was not found");

const index = courses.indexOf(course)


courses.splice(index, 1)
res.send(courses);
});

// Deleting a course
app.delete(‘/api/courses/:id’, (req, res) => {
// If course not found, return 404, otherwise delete it
// and return the deleted object.
});

// Writing routes in a separate folder using express.Router()


// router.route method:
Express: Advanced Topics
So, in this section, you learned that:
- A middleware function is a function that takes a request object and either
terminates the request/response cycle or passes control to another middleware
function.

In the server, REQUEST PROCESSING PIPELINE


=>Request=>midlleware functions: [json() => route()] => response

Ex1: here middleware function hadle the “/” route


app.get(
"/",
// => route handler function
(req, res) => {
res.send("welcome to vidly demo");
}
);

Ex2:
app.use(express.json());
// the express.json() will return middleware function
// it will parse the req, if there was a body in the req , then it will set
req.body

Ex3:
Ex4:
- You can create custom middleware for cross-cutting concerns, such as logging,
authentication, etc.

// Custom middleware (applied on all routes)


app.use(function(req, res, next)) {
// …
next();
}

app.use(function (req, res, next) {


console.log("Logging.....");
next();
});

app.use(function (req, res, next) {


console.log("Authentication");
next();
});

Ex 3: router.param middleware
Express has a few built-in middleware functions:

- json(): to parse the body of requests with a JSON payload


- urlencoded(): to parse the body of requests with URL-encoded payload
 express.urlencoded({ extended: true }) is a middleware in Express.js used for
parsing data from HTML forms submitted via the POST method.
 Use: It extracts form data from the request body, making it accessible in req.body.
This is essential when handling user inputs, such as login credentials or form
submissions, in an Express.js application.

- static(): to serve static files, like to view html pages,..


app.use(express.json());
app.use(express.urlencoded({ extended: true })); // to access body of the req
app.use(express.static("public")); // http://localhost:3000/readme.txt

Third party middleware functions:


https://expressjs.com/en/resources/middleware.html

app.use(helmet());
app.use(morgan("tiny"));

// Custom middleware (applied on routes starting with /api/admin)


app.use(‘/api/admin’, function(req, res, next)) {
// …
next();
}

Environment:
- We can detect the environment in which our Node application is running
(development, production, etc) using process.env.NODE_ENV and
app.get(‘env’). - The config package gives us an elegant way to store
configuration settings for
our applications.

console.log(process.env.NODE_ENV); // undefined
console.log(app.get("env")); // by default development

- We can use the debug package to add debugging information to an application.


Prefer this approach to console.log() statements.

/*
set NODE_ENV=production
*/
if (app.get("env") === "development") {
app.use(morgan("tiny"));
console.log("morgan enabled...");
}
Configuration:
// npm i config
const config = require("config");

Folder: config > default.json:


{
"name": "My Express App"
}

Congif > development.json:


{
"name": "My Express App - Development",
"mail" : {
"host" : "dev-ser-mail"
}
}

Config > production.json:


{
"name": "My Express App - Production",
"mail": {
"host": "pro-ser-mail"
}
}

Config > custom-environment-variables.json:


{
"mail": {
"password": "app_password"
}
}

Index.js
console.log("App name: " + config.get("name"));
console.log("mail: " + config.get("mail.host"));
console.log("App Password: " + config.get("mail.password"));
// set app_password=1234

Debugging:
// npm i debug
const startupDebbuger = require("debug")("app:startup");
const dbDebugger = require("debug")("app:db");
const morgan = require("morgan");
const express = require("express");
const app = express();

if (app.get("env") === "development") {


app.use(morgan("tiny"));
startupDebbuger("morgan enabled...");
}

// some db work...
dbDebugger("Connected to db");

const port = process.env.PORT || 3000;


app.listen(port, () => console.log(`Listening on port ${port}....`));

// set DEBUG=app:startup
// set DEBUG=app:db
// set DEBUG=app:*

Templating Engine:

- To return HTML markup to the client, use a templating engine. There are various
templating engines available out there. Pug, EJS and Mustache are the most
popular ones.

Ex1: pug

Views > index.pug


html
head
title= title
body
h1= message

index.js

// npm i pug
const morgan = require("morgan");
const express = require("express");
const app = express();

if (app.get("env") === "development") {


app.use(morgan("tiny"));
}

app.set("view engine", "pug");


app.set("views", "./views");

app.get("/", (req, res) => {


res.render("index", { title: "My Express App", message: "Hello" });
});

const port = process.env.PORT || 3000;


app.listen(port, () => console.log(`Listening on port ${port}....`));

Ex2: ejs

index.js
Database Integration:
https://expressjs.com/en/guide/database-integration.html

Structuring Express Application:

Middleware> logger.js

function log(req, res, next) {


console.log("Logging.....");
next();
}

module.exports = log;

routes > genres.js

const express = require('express')


const router = express.Router()
const Joi = require("joi");

const genres = [
{ id: 1, genre: "Action" },
{ id: 2, genre: "Horror" },
{ id: 3, genre: "comedy" },
{ id: 4, genre: "sci-fi" },
];

router.use(express.json());

router.get("/", (req, res) => {


res.send(genres);
});

router.post("/", (req, res) => {


const schema = Joi.object({
genre: Joi.string().min(3).required(),
});
const result = schema.validate(req.body);

if (result.error)
return res.status(400).send(result.error.details[0].message);

genres.push({
id: genres.length + 1,
genre: result.value.genre,
});
res.send(genres);
});

router.put("/:id", (req, res) => {


const { id } = req.params;
const genreIndex = genres.findIndex((g) => g.id === parseInt(id));

if (genreIndex === -1)


return res.status(404).send("The genre ID you are searching is not found");

const schema = Joi.object({


genre: Joi.string().min(3).required(),
});
const result = schema.validate(req.body);

if (result.error)
return res.status(400).send(result.error.details[0].message);

genres[genreIndex].genre = result.value.genre;

res.send(genres);
});

router.delete("/:id", (req, res) => {


const { id } = req.params;
const genreById = genres.findIndex((g) => g.id === parseInt(id));
if (genreById === -1)
return res.status(404).send("The genre ID you are searching is not found");
genres.splice(genreById, 1);
res.send(genres);
});

router.get("/:id", (req, res) => {


const { id } = req.params;
const genreById = genres.find((g) => g.id === parseInt(id));
if (!genreById)
return res.status(404).send("The genre ID you are searching is not found");
res.send(genreById);
});

module.exports = router

routes > home.js

const express = require("express");


const home = express.Router();

home.get("/", (req, res) => {


res.send("welcome to vidly demo");
});

module.exports = home

index.js

const express = require("express");


const app = express();
const genres = require("./routes/genres");
const home = require("./routes/home");
const log = require("./middleware/logger");

app.use(log);

app.use("/", home);
app.use("/api/genres", genres);

const port = process.env.PORT || 3000;


app.listen(port, () => console.log(`The connection is running on ${port}`));

You might also like