Nodejs Router
In Node.js, routing is a key part of handling HTTP requests. It determines how to dispatch requests based on different URLs and HTTP methods (such as GET, POST, PUT, DELETE, etc.).
Routing is commonly used to build web applications, especially RESTful APIs.
Node.js itself does not have a built-in routing mechanism, but it can be implemented through middleware libraries (like Express).
Routing typically involves the following aspects:
* **URL Matching**: Matching routing rules based on the request's URL.
* **HTTP Method Matching**: Matching routing rules based on the request's HTTP method (GET, POST, PUT, DELETE, etc.).
* **Request Handling**: Once a matching routing rule is found, the corresponding handler function is called to process the request.
In Node.js, we can create a simple route using the http module, as shown in the following example:
## Example
const http = require('http');
// Create server and define routes
const server = http.createServer((req, res)=>{
const{ url, method }= req;
if(url ==='/'&& method ==='GET'){
res.writeHead(200,{'Content-Type':'text/plain'});
res.end('Home Page');
}else if(url ==='/about'&& method ==='GET'){
res.writeHead(200,{'Content-Type':'text/plain'});
res.end('About Page');
}else{
res.writeHead(404,{'Content-Type':'text/plain'});
res.end('404 Not Found');
}
});
server.listen(3000,()=>{
console.log('Server is running on http://localhost:3000');
});
Visiting **http://localhost:3000** in the browser displays the following:
!(#)
Visiting **http://localhost:3000/about** in the browser displays the following:
!(#)
If you visit any other URL, it will directly display **404 Not Found**.
For more HTTP requests, you can refer to: (#).
* * *
## Request Parameters
A complete URL like http://localhost:8888/start?foo=bar&hello=world contains the host, path, and query string.
To parse this data, we can use the URL object and the querystring module.
const myUrl = new URL("http://localhost:8888/start?foo=bar&hello=world");// Extract pathname console.log(myUrl.pathname); // Output: /start// Extract query parameters console.log(myUrl.searchParams.get("foo")); // Output: bar console.log(myUrl.searchParams.get("hello")); // Output: world myUrl.pathname | | ----- http://localhost:8888/start?foo=bar&hello=world --- ----- | | | | myUrl.searchParams.get("foo") | | myUrl.searchParams.get("hello")
Of course, we can also use the querystring module to parse parameters in a POST request body. This will be covered in the later [Node.js GET/POST Requests](#).
All the request data we need is contained in the request object, which is passed as the first argument to the onRequest() callback function.
Now let's add some logic to the http module's onRequest() function to find the URL path requested by the browser:
## server.js File Code:
var http = require("http"); var url = require("url"); function start(){function onRequest(request, response){const pathname = new URL(request.url, `http:console.log(`Request for ${pathname}received.`); response.writeHead(200, {"Content-Type": "text/plain"}); response.write("Hello World"); response.end(); } http.createServer(onRequest).listen(8888); console.log("Server has started."); } module.exports.start = start;
Okay, our application can now distinguish different requests based on the requested URL path -- this allows us to use routing (not yet complete) to map requests to handlers based on the URL path.
In the application we are going to build, this means that requests from /start and /upload can be handled with different code. We will see how these are integrated together later.
Now we can write the routing. Create a file named **router.js** and add the following content:
## router.js File Code:
function route(pathname){console.log("About to route a request for " + pathname); }exports.route = route;
**router.js handles the routing logic, defining and exporting the route function, which is used to handle different paths when the server receives a request.**
Our server should be aware of the routing and use it effectively. We could certainly hardcode this dependency into the server, but programming experience from other languages tells us this would be a painful process, so we will use dependency injection to add the routing module more loosely.
First, let's extend the server's start() function to accept the route function as a parameter. The **server.js** file code is as follows:
## server.js File Code:
const http = require("http"); const{URL} = require("url"); function start(route){function onRequest(request, response){const pathname = new URL(request.url, `http:console.log(`Request for ${pathname}received.`); route(pathname); response.writeHead(200, {"Content-Type": "text/plain"}); response.write("Hello World"); response.end(); } http.createServer(onRequest).listen(8888); console.log("Server has started."); } module.exports.start = start;
**server.js defines the server's startup logic and calls the route function when a request is received.**
At the same time, we will extend index.js accordingly, so that the route function can be injected into the server:
## index.js File Code:
var server = require("./server"); var router = require("./router"); server.start(router.route);
**index.js is the entry point of the program, responsible for starting the server and passing the routing module to the server module.**
Now start the application (node index.js, always remember this command), then request a URL, and you will see the application output corresponding information, indicating that our HTTP server is already using the routing module and will pass the requested path to the route:
$ node index.js Server has started.
Visiting **http://localhost:8888/** in the browser, the server should print path-related routing messages in the console and return a "Hello World" response:
!(#)
The background terminal will display the access information:
Request for / received.About to route a request for /Request for /favicon.ico received.About to route a request for /favicon.ico
* * *
## Routing with Express
Express is a popular Node.js framework that provides powerful routing capabilities.
For more about Express, you can refer to: [Node.js Express Framework](#).
### Installing Express
First, make sure you have installed Express. If not, you can install it using npm:
npm install express
### Basic Routing
Here is a simple Express application demonstrating how to set up basic routing:
## Example
const express = require('express');
const app = express();
const port =3000;
// Define a GET route
app.get('/',(req, res)=>{
res.send('Hello, World!');
});
// Define a POST route
app.post('/submit',(req, res)=>{
res.send('Form submitted!');
});
// Start server
app.listen(port,()=>{
console.log(`Server is running on http://localhost:${port}`);
});
### Dynamic Routing
Dynamic routing allows you to use parameterized URLs.
For example, you can define a route to handle /users/:id, where :id is a dynamic parameter.
app.get('/users/:id', (req, res) => { const userId = req.params.id; res.send(`User ID: ${userId}`);});
### Route Parameters
Express allows you to extract parameters from the URL and access them via the req.params object.
## Example
app.get('/users/:id',(req, res)=>{
const userId = req.params.id;
res.send(`User ID: ${userId}`);
});
app.get('/search/:query',(req, res)=>{
const query = req.params.query;
res.send(`Search query: ${query}`);
});
### Query Parameters
Query parameters are key-value pairs in the URL, typically used to pass additional information. You can access query parameters via the req.query object.
app.get('/search', (req, res) => { const query = req.query.q; res.send(`Search query: ${query}`);});
### Route Middleware
Route middleware are functions that execute before or after handling a request. You can use middleware to handle tasks like authentication, logging, etc.
// Logging middlewareconst logger = (req, res, next) => { console.log(`Request Type: ${req.method} ${req.url}`); next();};// Use middleware app.use(logger); app.get('/', (req, res) => { res.send('Hello, World!');});
### Route Grouping
To better organize your code, you can use route grouping. Express provides the express.Router object, which can be used to create modular, mountable route handlers.
## Example
const express = require('express');
const app = express();
const port =3000;
// Create a router instance
const userRouter = express.Router();
// Define user-related routes
userRouter.get('/',(req, res)=>{
res.send('List of users');
});
userRouter.get('/:id',(req, res)=>{
const userId = req.params.id;
res.send(`User ID: ${userId}`);
});
// Mount the user router
app.use('/users', userRouter);
// Start server
app.listen(port,()=>{
console.log(`Server is running on http://localhost:${port}`);
});
### Advanced Routing Techniques
**1. Error Handling:** You can define error-handling middleware to catch and handle errors in routes.
app.use((err, req, res, next) => { console.error(err.stack); res.status(500).send('Something broke!');});
**2. Route Priority:** The order in which routes are defined determines their priority. Routes defined earlier are matched first.
**3. Route Restrictions:** You can use middleware to restrict access to certain routes, for example, allowing only authenticated users.
## Example
const authMiddleware =(req, res, next)=>{
if(req.headers.authorization){
next();
}else{
res.status(401).send('Unauthorized');
}
};
app.get('/admin', authMiddleware,(req, res)=>{
res.send('Admin page');
});
YouTip