Express

Created
TypeLibrary
LanguageJavascript
Last Edit

Description

Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.

Express 4.x - API Reference (expressjs.com)

Setup

Express Application

Import and call express function to create a new express application

const express = require("express");
const app = express();

Parse JSON

app.use(express.json());

This will by default parse json so that json is accessible as objects.

Routes

app.com:

app.get("", (req, res) => {
  res.send("Hello Express!");
});

app.com/help

app.get("/help", (req, res) => {
  res.send("Help Page");
});
req: Request from browser
res: Response to browser

404

app.get("/help/*", (req, res) => {
  res.send("Help article not found")
});

app.get("*", (req, res) => {
  res.send("My 404 page");
});

Listen

app.listen(3000, () => {
  console.log("Server is up on port 3000.");
});

Cors Options

Setup allowed origins and credentials requirement.

import cors from "cors";

const allowedOrigins = [
  "http://localhost:3000",
  "https://course-authoring-frontend-testing.onrender.com",
];

var corsOptions = {
  credentials: true,
  origin: allowedOrigins,
};

app.use(cors(corsOptions));

Hot Reload with Nodemon

Starting node app with following command will restart server whenever new changes are saved.

nodemon src/app.js

Return Data

HTML

app.get("", (req, res) => {
  res.send("<h1>Weather</h1>");
});

JSON

app.get("/help", (req, res) => {
  res.send({ name: "Andrew", age: 27 });
});

Static HTML Files

Files to be served are stored outside of src folder in public directory.

index.html, about.html, help.html stored in public folder

const path = require("path");
const express = require("express");

const app = express();

const publicDirectory = path.join(__dirname, "../public");
app.use(express.static(publicDirectory));

Visiting localhost:3000 will serve index.html and localhost:3000/about.html will serve about.html and so on.

All types of files inside public folder (css, js, images etc) can be accessed by html files using link, script, image tags.

Dynamic HTML Files

Using templating engine handlebars for express called hbs

npm i hbs

Setup express to use hbs:

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

Create a folder in root of project called views. It will contain dynamic files with extension .hbs

If views contain index.hbs file then render it for certain route with required data.

app.get("", (req, res) => {
  res.render("index", { title: "Weather App" });
});

index.hbs:

<html>
  <head>
    <link rel="stylesheet" href="/css/styles.css" />
    <script src="/js/app.js"></script>
    <title>Weather App</title>
  </head>
  <body>
    <h1>{{title}}</h1>
  </body></html>
CSS and JS files will be inside public folder but files in views can access them without mentioning the whole path.
Advanced templating with partials (header, footer) can be setup using hbs.registerPartials(partialsPath) and accessed using {{>header}} in index.hbs for example.

Handling Requests

Get Request

💡
Reference params in req in get variable specified.
app.get("/users/:id", async (req, res) => {
  const _id = req.params.id;
});

Post Request

💡
res.send to send data back.
app.post("/users", async (req, res) => {
 const body = req.body;
 res.send(body);
});

Patch Request

app.patch("/users/:id", async (req, res) => {
  const _id = req.params.id;
});

Delete Request

app.delete("/users/:id", async (req, res) => {
	const _id = req.params.id;
});

Validation

How To Use Joi for Node API Schema Validation | DigitalOcean

Status Codes

httpstatuses.org
This list is an easy-to-reference database of HTTP status codes with their definitions and helpful code references all in one place. Visit an individual status code via https://httpstatuses.com or browse the list below. This website is running as alternative of the original website httpstatuses.com, but with the old simple design.
https://httpstatuses.org/

200

app.post("/users", async (req, res) => {
  const user = new User(req.body);
  try {
    await user.save();
    res.status(200).send(user);
  }
});

400

app.post("/users", async (req, res) => {
  const user = new User(req.body);
  try {
    await user.save();
    res.status(200).send(user);
  }
	catch (e) {
	    res.status(400).send(e);
	  }
});

500

app.get("/users/:id", async (req, res) => {
  const _id = req.params.id;
  try {
    if (condition) {
      res.send(resData);
    } else {
      throw new Error("Invalid ID");
    }
  } catch (error) {
    res.status(500).send(error.message);
  }
});

Router

User Router

const express = require("express");
const router = new express.Router();

router.get("/user", (req, res) => {
  res.send("This is from my other router");
});

//... all other methods related to user here

module.exports = router;

Use Routes

const express = require("express");

const userRouter = require("./routers/user");
const taskRouter = require("./routers/task");

const app = express();
const port = process.env.PORT || 8000;

app.use(express.json());
app.use(userRouter); //user router
app.use(taskRouter); //task router

app.listen(port, () => {
  console.log("Server is up on port " + port);
});

Middleware

Middleware will allows up to make all the necessary routes (requests) authenticated, so that Express will only accept those requests with an authorisation token in the header.

Middleware will run once a new request has come in and before the route handler is run.

app.use((req, res, next) => {
  if (req.method === "GET") {
    res.send("GET requests are disabled");
  } else {
    next();
  }
});

Middlewares should be defined above all other app.use statements.

Maintenance Mode

app.use((req, res, next) => {
  res.status(503).send("Server In Maintenance Mode");
  next();
});

File Upload

npm i multer

const multer = require("multer");
const upload = multer({
  dest: "images",
});
app.post("/upload", upload.single("upload"), (req, res) => {
  res.send();
});
Postman

Validation

File Size Limit

const upload = multer({
  dest: "avatars",
  limits: {
    fileSize: 1000000, 
		//in bytes: 1MB
  },
});

File Type (Extension)

const upload = multer({
  dest: "avatars",
  limits: {
    fileSize: 1000000, //in bytes: 1MB
  },
  fileFilter(req, file, callback) {
    if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
      return callback(new Error("Please upload an image"));
    }
    callback(undefined, true);
  },
});

Error Handling

router.post(
  "/users/profile/avatar",
	auth,
  upload.single("avatar"),
  async (req, res) => {
    res.send();
  },
  (error, req, res, next) => {
    res.status(400).send({ error: error.message });
  }
);

Upload To Database

Remove dest from multer

const upload = multer({
  limits: {
    fileSize: 1000000, //in bytes: 1MB
  },
  fileFilter(req, file, callback) {
    if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
      return callback(new Error("Please upload an image"));
    }
    callback(undefined, true);
  },
});

Route Handler:

router.post(
  "/users/profile/avatar",
  auth,
  upload.single("avatar"),
  async (req, res) => {
    req.user.avatar = req.file.buffer;
    await req.user.save(); 
    res.send();
  },
  (error, req, res, next) => {
    res.status(400).send({ error: error.message });
  }
);

Render Image From Binary in HTML

<img src=”data:image/jpg;base64,BINARYSTRINGHERE" />

Image Resize & File Type

Resizing and converting image file before saving the binary in database.

const sharp = require("sharp");

const buffer = await sharp(req.file.buffer)
      .resize({ widht: 250, height: 250 })
      .png()
      .toBuffer();

req.user.avatar = buffer;
await req.user.save();
res.send();

File Serve

router.get("users/:id/avatar", async (req, res) => {
  const _id = req.params.id;
  try {
    if (mongoose.Types.ObjectId.isValid(_id)) {
      const user = await User.findById(_id);
      if (!user || !user.avatar) {
        throw new Error();
      }
      res.set("Content-Type", "image/jpg");
      res.send(user.avatar);
    } else {
      throw new Error("Invalid ID");
    }
  } catch (error) {
    res.status(400).send();
  }
});

Visiting {{host}}/users/636b34ec6b3026c9da4d4acf/avatar from browser will get the avatar of that particular user.

Also this URL can be set as src attribute of img tag to render the image.