Node.js Express Framework
Node.js - Express Framework
Section titled “Node.js - Express Framework”Express Overview
Section titled “Express Overview”Express (or Express.js) is a minimal, flexible, and highly popular web application framework for Node.js. It provides a thin layer of fundamental web application features, without obscuring Node.js features, making it ideal for building robust APIs and web applications quickly.
Core Features of Express:
- Routing: Defines how the application responds to client requests based on the URL (path) and HTTP method (GET, POST, PUT, DELETE, etc.).
- Middleware: Provides a powerful mechanism to execute functions sequentially during the request-response cycle. Middleware can perform tasks like logging, parsing request bodies, authentication, authorization, error handling, and more.
- Request/Response Helpers: Adds utility methods and properties to Node.js’s native request (
req) and response (res) objects, simplifying common web development tasks. - Templating Engine Integration: Easily integrates with various templating engines (like EJS, Pug, Handlebars) to render dynamic HTML pages.
- Focus on Performance: Express is designed to be lightweight and fast.
Installing Express
Section titled “Installing Express”First, ensure you have a Node.js project initialized with a package.json file (npm init -y). Then, install Express as a project dependency:
$ npm install expressThis command installs Express and adds it to the dependencies in your package.json.
While Express handles the core web framework features, you often need additional middleware for specific tasks. Some common ones include:
cors: Enables Cross-Origin Resource Sharing.helmet: Helps secure your Express apps by setting various HTTP headers.morgan: HTTP request logger middleware.dotenv: Loads environment variables from a.envfile.multer: Middleware for handlingmultipart/form-data, primarily used for file uploads.
Install them as needed, e.g.: $ npm install cors morgan
Note: Basic body parsing (JSON, URL-encoded) is now built into Express, so you often don’t need the separate body-parser package anymore.
Hello World Example
Section titled “Hello World Example”Here’s a minimal Express application that starts a server listening on port 3000 and responds to requests to the homepage (/).
// Import the express libraryconst express = require('express');
// Create an Express application instanceconst app = express();
// Define the port the server will listen onconst port = 3000;
// Define a route handler for GET requests to the root path ('/')app.get('/', (req, res) => { // req: request object, res: response object res.send('Hello World from Express!');});
// Start the server and listen for connections on the specified portapp.listen(port, () => { console.log(`Example Express app listening at http://localhost:${port}`);});Save this code in a file (e.g., app.js) and run it:
$ node app.jsYou’ll see the following output in your terminal:
Example Express app listening at http://localhost:3000Open your web browser and navigate to http://localhost:3000/. You should see the text “Hello World from Express!”. If you navigate to any other path (e.g., http://localhost:3000/other), Express will automatically respond with a 404 Not Found.
Request & Response Objects
Section titled “Request & Response Objects”Express route handlers receive two primary objects:
- Request Object (
req): Represents the incoming HTTP request. It contains information like: -
req.params: Route parameters (e.g.,/users/:userId).
-
req.query: URL query parameters (e.g.,/search?term=node).
-
req.body: Parsed request body (requires body-parsing middleware likeexpress.json()orexpress.urlencoded()).
-
req.headers: Incoming request headers.
-
req.method: HTTP method (GET, POST, etc.).
-
req.path: Request path.
-
req.ip: Client’s IP address.
- Response Object (
res): Represents the HTTP response that the Express app sends back. It provides methods for sending the response, such as: -
res.send(): Sends various types of responses (HTML, text, JSON automatically stringified).
-
res.json(): Sends a JSON response.
-
res.status(): Sets the HTTP status code.
-
res.sendFile(): Sends a file.
-
res.render(): Renders a view template.
-
res.redirect(): Redirects the request.
-
res.set(): Sets response headers.
Basic Routing
Section titled “Basic Routing”Routing determines how an application responds to specific endpoints (a combination of URI path and HTTP method).
The basic structure is app.METHOD(PATH, HANDLER), where METHOD is an HTTP method in lowercase (e.g., get, post, put, delete), PATH is the URL path (can include route parameters and patterns), and HANDLER is the function executed when the route is matched.
Let’s extend our example to handle different methods and paths:
const express = require('express');const app = express();const port = 3000;
// GET request to the homepageapp.get('/', (req, res) => { console.log('GET /'); res.send('Hello from GET /');});
// POST request to the homepageapp.post('/', (req, res) => { console.log('POST /'); // Note: To access req.body, you need middleware like express.json() console.log('Request Body:', req.body); res.send('Hello from POST /');});
// GET request for listing usersapp.get('/users', (req, res) => { console.log('GET /users'); res.json([{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]); // Send JSON data});
// GET request with a route parameter :userIdapp.get('/users/:userId', (req, res) => { const userId = req.params.userId; console.log(`GET /users/${userId}`); res.send(`Details for user ${userId}`);});
// DELETE request for a specific userapp.delete('/users/:userId', (req, res) => { const userId = req.params.userId; console.log(`DELETE /users/${userId}`); res.status(200).send(`User ${userId} deleted successfully.`); // Send status and message});
// Catch-all for any other GET request (basic 404)app.get('*', (req, res) => { res.status(404).send('Resource not found');});
app.listen(port, () => { console.log(`Express app with routing listening at http://localhost:${port}`);});Save and run this code. You can now test different requests:
- Browser/
curl GET http://localhost:3000/->Hello from GET / - Browser/
curl GET http://localhost:3000/users-> JSON array of users - Browser/
curl GET http://localhost:3000/users/123->Details for user 123 curl -X POST http://localhost:3000/->Hello from POST /curl -X DELETE http://localhost:3000/users/456->User 456 deleted successfully.- Browser/
curl GET http://localhost:3000/nonexistent->Resource not found(404 status)
Middleware
Section titled “Middleware”Middleware functions have access to the request (req), response (res), and the next function in the application’s request-response cycle. The next function passes control to the next middleware function. If the current middleware doesn’t end the cycle (by sending a response), it must call next().
Middleware can be used for:
- Executing any code.
- Making changes to the request and response objects.
- Ending the request-response cycle.
- Calling the next middleware in the stack.
Types of Middleware:
- Application-level: Bound to
appusingapp.use()orapp.METHOD(). - Router-level: Bound to an instance of
express.Router(). - Error-handling: Have 4 arguments (
err, req, res, next). Defined last. - Built-in: e.g.,
express.json(),express.urlencoded(),express.static(). - Third-party: Installed via npm (e.g.,
cors,morgan).
Example: Adding Built-in and Custom Middlewareconst express = require('express');const app = express();const port = 3000;
// Built-in middleware to parse JSON bodiesapp.use(express.json());
// Built-in middleware to parse URL-encoded bodiesapp.use(express.urlencoded({ extended: true }));
// Custom application-level middleware: Loggerapp.use((req, res, next) => { const timestamp = new Date().toISOString(); console.log(`${timestamp} - ${req.method} ${req.originalUrl}`); next(); // Pass control to the next middleware/route handler});
// Route using the parsed bodyapp.post('/data', (req, res) => { console.log('Received data:', req.body); res.json({ message: 'Data received successfully', data: req.body });});
app.get('/', (req, res) => { res.send('Homepage with logging!');});
// Error-handling middleware (defined last)app.use((err, req, res, next) => { console.error('Error caught:', err.stack); res.status(500).send('Something broke!');});
app.listen(port, () => { console.log(`Express app with middleware listening at http://localhost:${port}`);});Now, when you make requests, you’ll see log messages, and POST requests to /data with a JSON body will correctly parse req.body.
Serving Static Files
Section titled “Serving Static Files”Use the express.static built-in middleware to serve static assets like HTML, CSS, JavaScript files, and images.
Create a directory named public in your project root. Place static files inside it (e.g., public/index.html, public/css/style.css, public/images/logo.png).
Add the middleware to your app.js (usually near the top):
// Serve static files from the 'public' directoryapp.use(express.static('public'));Now, if you run the app, requests for files within the public directory will be served automatically:
http://localhost:3000/index.html-> Servespublic/index.htmlhttp://localhost:3000/css/style.css-> Servespublic/css/style.csshttp://localhost:3000/images/logo.png-> Servespublic/images/logo.png
You can mount the static directory on a specific path prefix: app.use('/static', express.static('public'));. Then files would be accessed via http://localhost:3000/static/index.html.
Handling Form Data (GET and POST)
Section titled “Handling Form Data (GET and POST)”Let’s create a simple HTML form and handle its submission.
Create public/form.html:
<!DOCTYPE html><html><head><title>Form Example</title></head><body> <h2>GET Form</h2> <form action="/process-get" method="GET"> First Name: <input type="text" name="first_name"><br> Last Name: <input type="text" name="last_name"><br> <input type="submit" value="Submit GET"> </form>
<hr>
<h2>POST Form</h2> <form action="/process-post" method="POST"> First Name: <input type="text" name="first_name"><br> Last Name: <input type="text" name="last_name"><br> <input type="submit" value="Submit POST"> </form></body></html>Update app.js to handle these form submissions:
const express = require('express');const app = express();const port = 3000;
// Middleware for static files and body parsingapp.use(express.static('public'));app.use(express.json());app.use(express.urlencoded({ extended: true }));
// --- Routes ---
app.get('/', (req, res) => { res.redirect('/form.html'); // Redirect root to the form});
// Handle GET request from formapp.get('/process-get', (req, res) => { // Data is in the query string for GET requests const response = { first_name: req.query.first_name, last_name: req.query.last_name }; console.log('GET Request Query:', response); res.json(response);});
// Handle POST request from formapp.post('/process-post', (req, res) => { // Data is in the request body for POST requests (needs urlencoded middleware) const response = { first_name: req.body.first_name, last_name: req.body.last_name }; console.log('POST Request Body:', response); res.json(response);});
// --- Server Start ---app.listen(port, () => { console.log(`Express form example listening at http://localhost:${port}`);});Run app.js and navigate to http://localhost:3000/. You’ll see the form. Submitting either form will send the data to the corresponding route, which will parse it (from req.query for GET, req.body for POST) and return it as JSON.
File Uploads
Section titled “File Uploads”Handling file uploads requires multipart/form-data encoding, which Express’s built-in parsers don’t handle. The multer middleware is commonly used for this.
Install multer: $ npm install multer
Create public/upload.html:
<!DOCTYPE html><html><head><title>File Upload</title></head><body> <h3>File Upload:</h3> <form action="/upload-file" method="POST" enctype="multipart/form-data"> Select file: <input type="file" name="myFile"><br> <input type="submit" value="Upload File"> </form></body></html>Update app.js:
const express = require('express');const multer = require('multer');const path = require('path');const fs = require('fs');
const app = express();const port = 3000;
// Ensure 'uploads' directory existsconst uploadDir = path.join(__dirname, 'uploads');if (!fs.existsSync(uploadDir)){ fs.mkdirSync(uploadDir);}
// Configure Multer// Store files in the 'uploads/' directory with their original namesconst storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, uploadDir); // Use the absolute path }, filename: function (req, file, cb) { // Use original name - caution: potential filename collisions/security issues // Consider adding unique IDs or timestamps for production cb(null, file.originalname); }});const upload = multer({ storage: storage });
// Middlewareapp.use(express.static('public'));// Note: Don't use express.json() or express.urlencoded() on the upload route if using multer
// Routesapp.get('/', (req, res) => { res.redirect('/upload.html');});
// Handle file upload POST request// 'myFile' must match the 'name' attribute of the <input type="file"> tagapp.post('/upload-file', upload.single('myFile'), (req, res, next) => { // req.file is the 'myFile' file // req.body will hold the text fields, if there were any
if (!req.file) { return res.status(400).send('No file uploaded.'); }
console.log('File uploaded successfully:'); console.log('Original Name:', req.file.originalname); console.log('Stored Path:', req.file.path); // Absolute path where stored console.log('Size:', req.file.size); console.log('MIME Type:', req.file.mimetype);
const response = { message: 'File uploaded successfully!', filename: req.file.originalname, path: req.file.path, size: req.file.size }; res.json(response);}, (error, req, res, next) => { // Handle potential multer errors res.status(400).send({ error: error.message });});
// Server Startapp.listen(port, () => { console.log(`Express file upload example listening at http://localhost:${port}`);});Run the app, go to http://localhost:3000/, select a file, and upload it. The file will be saved in the uploads directory (created if it doesn’t exist) in your project root, and you’ll receive a JSON response with file details.
Cookies Management
Section titled “Cookies Management”To parse and manage HTTP cookies, you typically need the cookie-parser middleware.
Install: $ npm install cookie-parser
Example:
const express = require('express');const cookieParser = require('cookie-parser');
const app = express();const port = 3000;
// Use cookie-parser middlewareapp.use(cookieParser());
app.get('/', (req, res) => { // Access cookies from the request object console.log('Cookies received: ', req.cookies);
// Set a cookie res.cookie('myCookie', 'someValue', { maxAge: 900000, httpOnly: true }); // Expires in 15 mins res.cookie('anotherCookie', 'moreData');
res.send('Hello! Check your browser cookies and server console.');});
app.get('/clear', (req, res) => { // Clear a cookie res.clearCookie('myCookie'); res.send('myCookie cleared.');});
app.listen(port, () => { console.log(`Express cookie example listening at http://localhost:${port}`);});Run this app, visit http://localhost:3000/. Check your browser’s developer tools (Application/Storage tab) to see the cookies being set. The server console will log any cookies sent by the browser on subsequent requests.