NodeJS Rest APIs
What is a REST API, and why is it used in Node.js?
A REST API (Representational State Transfer) is an architectural style for designing networked applications. It uses HTTP methods to perform operations (like GET, POST, PUT, DELETE) on resources, which are typically represented as JSON objects. REST APIs are widely used because they are simple, scalable, and can be consumed by a variety of clients, such as web, mobile, and desktop applications. In Node.js, REST APIs are commonly built using frameworks like Express to create routes and handle HTTP requests.
How do you create a basic REST API in Node.js using Express?
To create a basic REST API in Node.js using Express, you first need to install the Express framework, define routes to handle HTTP methods (GET, POST, PUT, DELETE), and set up your server.
Example of creating a basic REST API:
const express = require('express');
const app = express();
app.use(express.json()); // Parse incoming JSON requests
// GET request - Retrieve data
app.get('/api/users', (req, res) => {
res.send([{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]);
});
// POST request - Create new data
app.post('/api/users', (req, res) => {
const newUser = req.body;
res.status(201).send(newUser);
});
// PUT request - Update existing data
app.put('/api/users/:id', (req, res) => {
const userId = req.params.id;
const updatedUser = req.body;
res.send({ id: userId, ...updatedUser });
});
// DELETE request - Delete data
app.delete('/api/users/:id', (req, res) => {
const userId = req.params.id;
res.send({ message: `User with ID ${userId} deleted` });
});
// Start the server
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
In this example, the API defines routes for the basic CRUD (Create, Read, Update, Delete) operations and listens on port 3000.
What are the main HTTP methods used in REST APIs?
The main HTTP methods used in REST APIs include:
- GET: Retrieves data from the server (e.g., fetching a list of users).
- POST: Sends data to the server to create a new resource (e.g., creating a new user).
- PUT: Updates an existing resource with new data (e.g., updating a user's information).
- DELETE: Deletes a resource from the server (e.g., deleting a user).
How do you handle query parameters and URL parameters in a REST API?
In REST APIs, query parameters and URL parameters allow clients to pass additional information to the server. Query parameters are part of the URL after a question mark (?), while URL parameters are part of the URL path itself. Both can be accessed in Express.
Example of handling query and URL parameters:
const express = require('express');
const app = express();
// URL parameter
app.get('/api/users/:id', (req, res) => {
const userId = req.params.id; // Access URL parameter
res.send({ id: userId, name: 'John' });
});
// Query parameter
app.get('/api/search', (req, res) => {
const searchTerm = req.query.q; // Access query parameter
res.send({ message: `Searching for ${searchTerm}` });
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
In this example, the id is a URL parameter, and q is a query parameter passed as part of the URL.
How do you handle request body data in a REST API?
To handle request body data in a REST API, you need to parse incoming JSON or form data. In Express, you can use the express.json() middleware to parse JSON data in the request body.
Example of handling request body data:
const express = require('express');
const app = express();
app.use(express.json()); // Parse incoming JSON requests
app.post('/api/users', (req, res) => {
const newUser = req.body; // Access the request body
res.status(201).send(newUser);
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
In this example, the express.json() middleware parses the incoming JSON request body, allowing you to access the data with req.body.
How do you handle errors in a REST API?
Error handling in REST APIs is important for providing meaningful feedback to clients when something goes wrong. You can handle errors by sending appropriate HTTP status codes and error messages. In Express, you can use the next() function to pass errors to error-handling middleware.
Example of handling errors:
const express = require('express');
const app = express();
app.use(express.json());
// Route with an error
app.get('/api/users/:id', (req, res, next) => {
const userId = req.params.id;
if (isNaN(userId)) {
const error = new Error('Invalid user ID');
error.status = 400; // Bad Request
return next(error); // Pass the error to the error handler
}
res.send({ id: userId, name: 'John' });
});
// Error-handling middleware
app.use((err, req, res, next) => {
res.status(err.status || 500).send({ error: err.message });
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
In this example, if the user ID is not a valid number, an error is thrown and passed to the error-handling middleware, which sends an appropriate error response to the client.
What are status codes, and how do you use them in a REST API?
Status codes are part of the HTTP response sent by the server to indicate the result of the client's request. They are categorized into different groups:
- 2xx: Success (e.g., 200 OK, 201 Created).
- 4xx: Client error (e.g., 400 Bad Request, 404 Not Found).
- 5xx: Server error (e.g., 500 Internal Server Error).
You can use these status codes in Express by calling res.status() before sending the response.
Example of using status codes:
const express = require('express');
const app = express();
app.post('/api/users', (req, res) => {
const newUser = req.body;
if (!newUser.name) {
return res.status(400).send({ error: 'Name is required' }); // 400 Bad Request
}
res.status(201).send(newUser); // 201 Created
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
In this example, the API sends a 400 status code if the request body is missing the name, and a 201 status code when a new user is created.
How do you use middleware in Express to build a REST API?
Middleware in Express is a function that executes during the request-response cycle. It can be used to modify the request, response, or handle errors. Middleware functions are used for tasks like logging, authentication, parsing, and error handling.
Example of using middleware in Express:
const express = require('express');
const app = express();
// Logging middleware
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next(); // Proceed to the next middleware or route handler
});
// Body parser middleware
app.use(express.json());
// Simple route
app.get('/api/users', (req, res) => {
res.send([{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]);
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
In this example, a logging middleware logs each request to the console before passing control to the route handler. The express.json() middleware is also used to parse incoming JSON data.
How do you handle authentication and authorization in a REST API?
Authentication and authorization in a REST API ensure that only authenticated users can access protected resources, and only authorized users can perform certain actions. You can implement authentication using techniques like JWT (JSON Web Tokens), OAuth, or session-based authentication. Authorization involves checking user roles or permissions to restrict access to certain endpoints.
Example of handling JWT-based authentication:
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
// Middleware to authenticate using JWT
function authenticateJWT(req, res, next) {
const token = req.header('Authorization') && req.header('Authorization').split(' ')[1];
if (!token) {
return res.status(401).send({ error: 'Unauthorized' });
}
jwt.verify(token, 'yourSecretKey', (err, user) => {
if (err) {
return res.status(403).send({ error: 'Forbidden' });
}
req.user = user;
next();
});
}
// Protected route
app.get('/api/protected', authenticateJWT, (req, res) => {
res.send({ message: 'This is a protected route' });
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
In this example, the authenticateJWT middleware verifies the JWT token sent in the Authorization header. If the token is valid, the request proceeds to the protected route. If not, the request is denied with a 401 or 403 status code.
What is CORS, and how do you handle it in a REST API?
CORS (Cross-Origin Resource Sharing) is a security feature implemented by browsers that restricts web pages from making requests to a domain other than the one from which the page was served. To allow cross-origin requests in a REST API, you need to configure the server to include the appropriate CORS headers.
Example of handling CORS in Express using the cors package:
const express = require('express');
const cors = require('cors');
const app = express();
// Enable CORS for all routes
app.use(cors());
app.get('/api/users', (req, res) => {
res.send([{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]);
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
In this example, the cors() middleware is used to enable CORS for all routes, allowing cross-origin requests from any domain.