In module 8, we will dive into the building RESTful APIs with 
           
           
            Express.js, an important skill for web developers.
           
           
            
           
           8.1 Building RESTful APIs using Express
           
            What is a RESTful API?
           
           
            A RESTful API (Representational State Transfer Application 
           
           
            Programming Interface) is a set o
            f rules and conventions for building 
           
           
            and interacting with web services. RESTful APIs use HTTP requests to 
           
           
            perform CRUD operations on resources represented as URLs, follow 
           
           
            a 
            stateless client-server architecture, and use standard HTTP 
           
           
            methods (GET, POST, PUT, DELETE) for operations.
           
           
           
             Express.js, a popular Node.js framework, is commonly used to 
           
           
            build RESTful APIs due to its simplicity and flexibility.
           
           
            
           
           Creating an Express.js API
           
            To create a RESTful API with Express, you need to
             set up routes and 
           
           
            define how the API responds to different HTTP methods and request 
           
           
            URLs. Here's a basic example of creating a simple API for managing 
           
           
            tasks:
           
           
            - javascript
           
           
            const express = require('express');
           
           
            const bodyParser = require('body-parser');
           
           
            const app = express();
           
           
            const port = 3000;
           
           
            // Middleware to parse JSON request bodies
           
           
            app.use(bodyParser.json());
           
           
            // Mock data (replace with a database in production)
           
           
            let tasks = [
           
           
             { id: 1, title: 'Task 1', completed: false },
           
           
             { id: 2, title: 'Task 2', completed: true },
           
           
            ];
           
           
            // GET all tasks
           
           
            app.get('/tasks', (req, res) => {
           
           
             res.json(tasks);
           
           
            });
           
           
            // GET a specific task by ID
           
           
            app.get('/tasks/:id', (req, res) => {
           
           
             const id = parseInt(req.params.id);
           
           
             const task = tasks.find((t) => t.id === id);
           
           
             if (!task) {
           
           
             return res.status(404).json({ error: 'Task not found' });
           
           
             }
           
           
             res.json(task);
           
           
            });
           
           
            // POST (create) a new task
           
           
            app.post('/tasks', (req, res) => {
           
           
             const newTask = req.body;
           
           
             newTask.id = tasks.length + 1;
           
           
             tasks.push(newTask);
           
           
             res.status(201).json(newTask);
           
           
            });
           
           
            // PUT (update) a task by ID
           
           
            app.put('/tasks/:id', (req, res) => {
           
           
             const id = parseInt(req.params.id);
           
           
             const updatedTask = req.body;
           
           
             let taskIndex = tasks.findIndex((t) => t.id === id);
           
           
             if (taskIndex === -1) {
           
           
             return res.status(404).json({ error: 'Task not found' });
           
           
             }
           
           
             tasks[taskIndex] = { ...tasks[taskIndex], ...updatedTask };
           
           
             res.json(tasks[taskIndex]);
           
           
            });
           
           
            // DELETE a task by ID
           
           
            app.delete('/tasks/:id', (req, res) => {
           
           
             const id = parseInt(req.params.id);
           
           
             const taskIndex = tasks.findIndex((t) => t.id === id);
           
           
             if (taskIndex === -1) {
           
           
             return res.status(404).json({ error: 'Task not found' });
           
           
             }
           
           
             tasks.splice(taskIndex, 1);
           
           
             res.status(204).send();
           
           
            });
           
           
            app.listen(port, () => {
           
           
             console.log(`Server is running on port ${port}`);
           
           
            });
           
           
            In this example:
           
           
             We set up routes for different HTTP methods (`GET`, `POST`, 
           
           
            `PUT`, `DELETE`) to handle CRUD operations.
           
           
             Middleware (`body-parser`) is used to parse JSON request 
           
           
            bodies.
           
           
             Mock data (`tasks`) is used to simulate a database.
           
           
           
            8.2 Handing CRUD Operations
           
           
            
           
           CRUD Operations and RESTful APIs CRUD operations (Create, Read, 
           
            Update, Delete) are fundamental to working with RESTful APIs. 
           
           
            Here's how Express.js handles these operations:
           
           
            Create (POST): Create new resources by sending a POST request to 
           
           
            the API endpoint. In the example above, we create a new task using 
           
           
            `POST /tasks`.
           
           
            Read (GET): Retrieve resources using GET requests. You can fetch all 
           
           
            resources (`GET /tasks`) or a specific resource by its identifier (`GET 
           
           
            /tasks/:id`).
           
           
            Update (PUT): Update existing resources with PUT requests. The 
           
           
            example uses `PUT /tasks/:id` to update a task by its ID.
           
           
            Delete (DELETE): Delete resources with DELETE requests. The route 
           
           
            `DELETE /tasks/:id` deletes a task by its ID.
           
           
            Input Validation and Error Handling
           
           
            In a production-ready API, input validation and error handling are 
           
           
            crucial to ensure the security and reliability of your API.
           
           
            Input Validation: Validate and sanitize user inputs to prevent 
           
           
            malicious data from entering your API. You can use libraries like 
           
           
            “express-validator” to perform validation.
           
           
            Error Handling: Implement error handling middleware to gracefully 
           
           
            handle errors and return appropriate error responses. Express.js 
           
           
            provides a way to catch and handle errors in a central location, as 
           
           
            shown in Module 7.
           
           
            
           
           8.3 Versioning and API Documentation
           
            Versioning Your API
           
           
            As your API evolves, it's essential to maintain backward compatibility 
           
           
            while introducing new features or changes. API versioning allows you 
           
           
            to do this by providing different versions of your API to clients.
           
           
            There are several approaches to versioning your API:
           
           
            URL Versioning: Include the version in the URL, e.g., `/v1/tasks` and 
           
           
            `/v2/tasks`. This is straightforward and visible in the request.
           
           
            Header Versioning: Specify the version in the request headers. It 
           
           
            keeps the URL clean but requires clients to set the appropriate 
           
           
            header.
           
           
            Media Type Versioning: Use different media types (e.g., JSON or 
           
           
            XML) for different versions. Clients specify the desired version by 
           
           
            selecting the media type in the request header.
           
           
            Here's an example of URL versioning in Express.js:
           
           
            - javascript
           
           
            // Version 1
           
           
            app.get('/v1/tasks', (req, res) => {
           
           
             // ...
           
           
            });
           
           
            // Version 2
           
           
            app.get('/v2/tasks', (req, res) => {
           
           
             // ...
           
           
            });
           
           
            
           
           API Documentation
           
            API documentation is crucial for developers who use your API. It 
           
           
            provides information about available endpoints, request and 
           
           
            response formats, authentication, and usage examples. Welldocumented APIs are easier to understand and integrate.
           
           
            There are tools and libraries available to generate API 
           
           
            documentation, such as Swagger, OpenAPI, or tools like “apidoc”. 
           
           
            These tools can generate documentation from inline comments in 
           
           
            your code or by defining a separate documentation file.
           
           
            Here's an example of documenting an API endpoint using “apidoc”:
           
           
            javascript
           
           
            /**
           
           
            * @api {get} /tasks Request all tasks
           
           
            * @apiName GetTasks
           
           
            * @apiGroup Tasks
           
           
            *
           
           
            * @apiSuccess {Object[]} tasks List of tasks.
           
           
            * @apiSuccess {Number} tasks.id Task ID.
           
           
            * @apiSuccess {String} tasks.title Task title.
           
           
            * @apiSuccess {Boolean} tasks.completed Task completion status.
           
           
            *
           
           
            * @apiSuccessExample Success-Response:
           
           
            * HTTP/1.1 200 OK
           
           
            * [
           
           
            * {
           
           
            * "id": 1,
           
           
            * "title": "Task 1",
           
           
            * "completed": false
           
           
            * },
           
           
            * {
           
           
            *
           
           
             "id": 2,
           
           
            * "title": "Task 2",
           
           
            * "completed": true
           
           
            * }
           
           
            * ]
           
           
            */
           
           
            app.get('/tasks', (req, res) => {
           
           
             res.json(tasks);
           
           
            });
           
           
            In this example, we use “apidoc” annotations to describe the 
           
           
            endpoint, its name, group, expected response, and example 
           
           
            response data. Running the “apidoc” tool generates HTML 
           
           
            documentation from these comments.