1. Routing
1. Routing in ExpressJS
The breakdown of Express.js routing examples for the most common HTTP methods:
π Routing in Express.js β Examples
const express = require('express');const app = express();
// To parse JSON bodies (from POST/PUT requests)app.use(express.json());
/** π Home Route (GET) */app.get('/', function(req, res) { res.send('Welcome to the homepage!');});
/** β Create Data (POST) */app.post('/data', function(req, res) { const newData = req.body; // get data from client // logic to save newData... res.send(`Received new data: ${JSON.stringify(newData)}`);});
/** π Update Data (PUT) */app.put('/data/:id', function(req, res) { const id = req.params.id; const updatedData = req.body; // logic to update data with id... res.send(`Updated data with ID ${id}: ${JSON.stringify(updatedData)}`);});
/** β Delete Data (DELETE) */app.delete('/data/:id', function(req, res) { const id = req.params.id; // logic to delete data with id... res.send(`Deleted data with ID ${id}`);});
// Start the serverapp.listen(3000, function() { console.log('Server is listening on port 3000');});
π Quick Summary
HTTP Method | Route | Purpose |
---|---|---|
GET | / | Read homepage |
POST | /data | Create new data |
PUT | /data/:id | Update data by ID |
DELETE | /data/:id | Delete data by ID |
app.use(express.json());
Without it, req.body
will be undefined
in a POST or PUT request that sends JSON.
π§ Why?
Middleware like express.json()
inspects the incoming request and parses the body into a usable JavaScript object, attaching it to req.body
.
2. Advance Routing
2.1 Route Parameters and Query Strings
Route parameters allow you to pass data via the URL itself. Query strings are often used for optional data that isnβt part of the URL path.
const express = require('express');const app = express();
// Route with a parameter (e.g., /user/123)app.get('/user/:id', (req, res) => { const userId = req.params.id; res.send(`User ID: ${userId}`);});
// Route with a query string (e.g., /search?name=John)app.get('/search', (req, res) => { const name = req.query.name; res.send(`Searching for: ${name}`);});
app.listen(3000, () => { console.log('Server running on port 3000');});
Explanation:
-
Route Parameters: In
/user/:id
,:id
is a dynamic segment that can match any value. Thereq.params.id
retrieves the value from the URL. -
Query Strings: The route
/search
captures query strings likename=John
. These are accessed viareq.query.name
.
2.2 Route Handling with Multiple HTTP Methods
Express allows you to handle the same route for different HTTP methods like GET
, POST
, PUT
, DELETE
.
const express = require('express');const app = express();
// GET routeapp.get('/profile', (req, res) => { res.send('Viewing profile');});
// POST route (for updating profile)app.post('/profile', (req, res) => { res.send('Profile updated');});
// PUT route (for updating a specific part of the profile)app.put('/profile', (req, res) => { res.send('Profile completely updated');});
// DELETE route (for deleting profile)app.delete('/profile', (req, res) => { res.send('Profile deleted');});
app.listen(3000, () => { console.log('Server running on port 3000');});
Explanation:
- Each HTTP method (GET, POST, PUT, DELETE) corresponds to a different type of action on the
/profile
route. GET
is used to retrieve information,POST
to create or update data,PUT
to completely replace data, andDELETE
to remove data.
2.3 Route Handling with Regular Expressions (Regex)
You can use regular expressions in route paths for more flexible matching.
const express = require('express');const app = express();
// Match any route that starts with '/user/' followed by a numberapp.get('/user/:id([0-9]+)', (req, res) => { const userId = req.params.id; res.send(`User ID (only numbers): ${userId}`);});
// Match only routes with '/product/' followed by either 'apple' or 'banana'app.get('/product/:name(apple|banana)', (req, res) => { const productName = req.params.name; res.send(`Product: ${productName}`);});
app.listen(3000, () => { console.log('Server running on port 3000');});
Explanation:
:id([0-9]+)
uses a regular expression to match only numericid
s, preventing non-numeric IDs.:name(apple|banana)
restricts the value of:name
to apple or banana, ensuring that other products are not matched.
2.4 Chained Route Handlers
You can chain multiple middleware or route handlers for a single route, making the code more modular.
Example:
const express = require('express');const app = express();
// Middleware for loggingfunction logRequest(req, res, next) { console.log(`Received ${req.method} request at ${req.url}`); next();}
// Middleware for user authenticationfunction checkAuth(req, res, next) { const token = req.headers['authorization']; if (token === 'valid-token') { next(); // User is authenticated, proceed } else { res.status(401).send('Unauthorized'); }}
// Route with multiple handlersapp.get('/profile', logRequest, checkAuth, (req, res) => { res.send('Profile page for authenticated user');});
app.listen(3000, () => { console.log('Server running on port 3000');});
Explanation:
logRequest
: Logs each request that reaches the/profile
route.checkAuth
: Verifies if the request contains a validauthorization
token.- Both middlewares are applied in a chain, and only if all pass, the final handler (
(req, res) => { res.send('Profile page...')}
) sends the response.
2.5 Route Grouping with express.Router()
To organize your routes more effectively, you can group them using the express.Router()
.
const express = require('express');const app = express();
// Create a router for 'users' route groupconst userRouter = express.Router();
// Define user-specific routesuserRouter.get('/:id', (req, res) => { const userId = req.params.id; res.send(`User profile for ID: ${userId}`);});
userRouter.post('/', (req, res) => { res.send('User created');});
// Mount the router at '/users' pathapp.use('/users', userRouter);
// General route for productsapp.get('/products', (req, res) => { res.send('Product list');});
app.listen(3000, () => { console.log('Server running on port 3000');});
Explanation:
express.Router()
: This allows you to group routes into logical modules (like user-related routes in this example).app.use('/users', userRouter)
mounts the user-specific routes at the/users
base path.- Route paths are relative to the
/users
path, so/users/:id
will handle/users/123
.
2.6 Dynamic Route Parameters
In more advanced scenarios, you might want to capture a dynamic route part and use it to match multiple patterns.
const express = require('express');const app = express();
// Dynamic route that can accept different user types (admin, guest, member)app.get('/profile/:userType(admin|guest|member)', (req, res) => { const userType = req.params.userType; res.send(`You are logged in as ${userType}`);});
app.listen(3000, () => { console.log('Server running on port 3000');});
Explanation:
:userType(admin|guest|member)
matches one of the three types (admin
,guest
,member
), and the handler retrieves that value fromreq.params.userType
.- You can extend this to match different types of user routes or even dynamically fetch content based on the user type.
2.7 Catch-All Routes for 404 Error Handling
You can define a catch-all route for undefined routes and handle 404 errors.
const express = require('express');const app = express();
// Your actual routesapp.get('/home', (req, res) => { res.send('Home Page');});
// Catch-all route for undefined routesapp.use((req, res) => { res.status(404).send('Sorry, we could not find that route!');});
app.listen(3000, () => { console.log('Server running on port 3000');});
Explanation:
- The
app.use()
without a path will match any route that is not already matched by previous routes. - Itβs typically used to handle 404 errors or as a fallback handler.