Title: Building RESTful APIs with Express.js
Building RESTful APIs with Express.js involves creating a server that handles HTTP requests, manipulates resources, and returns appropriate responses. This chapter covers how to set up RESTful routes for CRUD operations, handle JSON data, integrate middleware, manage authentication/authorization, and document APIs using Swagger.
A. Setting Up Routes for CRUD Operations
Express.js makes setting up RESTful routes for CRUD (Create, Read, Update, Delete) operations straightforward.
-
Basic CRUD Routes Example:
-
Create (POST):
UsePOSTto create a new resource.app.post("/api/products", (req, res) => { // Code to add a new product res.status(201).send({ message: "Product created successfully" }); }); -
Read (GET):
UseGETto retrieve resources.app.get("/api/products", (req, res) => { // Code to fetch all products res.status(200).json(products); }); app.get("/api/products/:id", (req, res) => { // Code to fetch product by ID res.status(200).json(product); }); -
Update (PUT):
UsePUTto update an existing resource.app.put("/api/products/:id", (req, res) => { // Code to update a product by ID res.status(200).send({ message: "Product updated successfully" }); }); -
Delete (DELETE):
UseDELETEto remove a resource.app.delete("/api/products/:id", (req, res) => { // Code to delete a product by ID res.status(204).send(); });
-
B. Handling JSON Data in Requests
In RESTful APIs, clients often send data in JSON format. Express provides the express.json() middleware to parse incoming JSON data in request bodies.
-
Example of Handling JSON Data:
const express = require("express"); const app = express(); // Middleware to parse JSON data app.use(express.json()); app.post("/api/products", (req, res) => { const product = req.body; // Code to add product to database res.status(201).send({ message: "Product created successfully", product }); });- In this example,
req.bodycontains the parsed JSON data sent by the client.
- In this example,
-
Validation of JSON Data: You can use validation libraries like
joito validate incoming JSON data.const Joi = require("joi"); const schema = Joi.object({ name: Joi.string().min(3).required(), price: Joi.number().required(), }); app.post("/api/products", (req, res) => { const { error } = schema.validate(req.body); if (error) return res.status(400).send(error.details[0].message); // Code to add product to database res.status(201).send({ message: "Product created successfully" }); });
C. Integrating Middleware with RESTful APIs
Middleware in Express.js functions between the request and response cycle, making it ideal for logging, authentication, data validation, and error handling.
-
Example of Middleware Usage:
-
Logging Middleware:
const logger = (req, res, next) => { console.log(`${req.method} request to ${req.url}`); next(); // Proceed to the next middleware or route handler }; app.use(logger); -
Authentication Middleware:
const authenticate = (req, res, next) => { const token = req.headers["authorization"]; if (!token) return res.status(401).send("Access Denied"); // Verify token logic here next(); // Proceed if authentication is successful }; app.use("/api/products", authenticate); // Apply middleware to product routes -
Error Handling Middleware:
app.use((err, req, res, next) => { console.error(err.stack); res.status(500).send("Something went wrong!"); });
-
D. Authentication and Authorization in RESTful APIs
Authentication verifies the identity of a user, while authorization ensures the user has permission to access a resource. Express.js can handle both using middleware.
-
Example of Token-Based Authentication (JWT):
-
Install JWT:
npm install jsonwebtoken -
JWT Authentication Example:
const jwt = require("jsonwebtoken"); const authenticate = (req, res, next) => { const token = req.headers["authorization"]; if (!token) return res.status(401).send("Access Denied"); try { const verified = jwt.verify(token, "secretKey"); req.user = verified; next(); // Continue if the token is valid } catch (err) { res.status(400).send("Invalid token"); } }; // Protecting routes with authentication middleware app.use("/api/products", authenticate);
-
Authorization Example:
const authorizeAdmin = (req, res, next) => { if (req.user.role !== "admin") return res.status(403).send("Access forbidden"); next(); // Allow access for admins }; app.put("/api/products/:id", [authenticate, authorizeAdmin], (req, res) => { // Only admins can update products res.status(200).send("Product updated"); });
-
E. Documenting APIs with Swagger
Documenting your API ensures that developers can easily understand and use your API. Swagger is a popular tool for creating API documentation.
-
Setting Up Swagger in Express:
-
Install Swagger Dependencies:
npm install swagger-jsdoc swagger-ui-express -
Basic Swagger Setup:
const swaggerUi = require("swagger-ui-express"); const swaggerJsDoc = require("swagger-jsdoc"); const swaggerOptions = { swaggerDefinition: { openapi: "3.0.0", info: { title: "Product API", version: "1.0.0", description: "API for managing products", }, }, apis: ["./routes/*.js"], // Path to API files }; const swaggerDocs = swaggerJsDoc(swaggerOptions); app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocs)); -
Adding Swagger Comments to Your API:
/** * @swagger * /api/products: * get: * summary: Retrieve a list of products * responses: * 200: * description: A list of products. */ app.get("/api/products", (req, res) => { res.status(200).json(products); });
- Accessing the Documentation:
After setting up Swagger, you can access the API documentation at/api-docs.
-
Conclusion
Building RESTful APIs with Express.js involves setting up routes, handling JSON data, integrating middleware, and managing authentication and authorization. Documenting the API with tools like Swagger ensures ease of use for other developers. Following these best practices ensures that your APIs are efficient, secure, and scalable.