HTTP Basic
const http = require('http');
const server = http.createServer((req, res) => {
const url = req.url;
// Home page
if (url === '/') {
res.writeHead(200, { 'content-type': 'text/html' });
res.write('<h1>home page</h1>');
res.end();
}
// About page
else if (url === '/about') {
res.writeHead(200, { 'content-type': 'text/html' });
res.write('<h1>about page</h1>');
res.end();
}
// 404
else {
res.writeHead(404, { 'content-type': 'text/html' });
res.write('<h1>page not found</h1>');
res.end();
}
});
server.listen(5000);
For more details on MIME types (IANA media types).
Sending HTML Files in res.send()
const http = require('http');
const { readFileSync } = require('fs');
// Get all files
const homePage = readFileSync('./navbar-app/index.html');
const homeStyles = readFileSync('./navbar-app/styles.css');
const homeImage = readFileSync('./navbar-app/logo.svg');
const homeLogic = readFileSync('./navbar-app/browser-app.js');
const server = http.createServer((req, res) => {
const url = req.url;
// Home page
if (url === '/') {
res.writeHead(200, { 'content-type': 'text/html' });
res.write(homePage);
res.end();
}
// About page
else if (url === '/about') {
res.writeHead(200, { 'content-type': 'text/html' });
res.write('<h1>about page</h1>');
res.end();
}
// Styles
else if (url === '/styles.css') {
res.writeHead(200, { 'content-type': 'text/css' });
res.write(homeStyles);
res.end();
}
// Image/logo
else if (url === '/logo.svg') {
res.writeHead(200, { 'content-type': 'image/svg+xml' });
res.write(homeImage);
res.end();
}
// Logic
else if (url === '/browser-app.js') {
res.writeHead(200, { 'content-type': 'text/javascript' });
res.write(homeLogic);
res.end();
}
// 404 error page
else {
res.writeHead(404, { 'content-type': 'text/html' });
res.write('<h1>page not found</h1>');
res.end();
}
});
server.listen(5000);
Commonly Used HTTP Status Codes
Status Code | Status Text |
200 | OK |
201 | CREATED |
202 | ACCEPTED |
400 | BAD_REQUEST |
401 | UNAUTHORIZED |
404 | NOT_FOUND |
405 | METHOD_NOT_ALLOWED |
500 | INTERNAL_SERVER_ERROR |
502 | BAD_GATEWAY |
Express Basics
const express = require('express');
const app = express();
app.get('/', (req, res) => {
console.log('User hit the resource');
res.status(200).send('Home Page');
});
app.get('/about', (req, res) => {
res.status(200).send('About Page');
});
// '*' represents all other endpoints which are not defined above
app.all('*', (req, res) => {
res.status(404).send('<h1>Resource not found</h1>');
});
app.listen(5000, () => {
console.log('Server is listening on port 5000...');
});
π‘ Tip: Send static files in Express using static middleware
app.use(express.static('./public'));
const express = require('express');
const path = require('path');
const app = express();
// Setup static and middleware
app.use(express.static('./public'));
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, './navbar-app/index.html'));
});
app.all('*', (req, res) => {
res.status(404).send('Resource not found');
});
app.listen(5000, () => {
console.log('Server is listening on port 5000....');
});
π‘ Tip: You can keep index.html
inside the public folder, then you wonβt require to write the '/'
endpoint get request.
JSON Basics
Check out the JSON MDN docs.
res.json(null);
res.json({ user: 'tobi' });
res.status(500).json({ error: 'message' });
Params Query
app.get('/api/products/:id', (req, res) => {
const idx = data.products.findIndex(product => product.id === parseInt(req.params.id));
if (idx === -1) {
res.status(404).json('Product not found');
return;
}
res.json(data.products[idx]);
});
Complex Params Query
app.get('/api/products/:productID/reviews/:reviewID', (req, res) => {
const productID = parseInt(req.params.productID);
const reviewID = parseInt(req.params.reviewID);
const product = data.products.find(product => product.id === productID);
const review = product.reviews.find(review => review.reviewId === reviewID);
if (product && review) {
res.json(review);
} else {
res.status(404).json('Product or review not found');
}
});
Multiple Query URL Routes req.query()
Example URL: http://localhost:5000/api/v1/query?name=john&id=12
Check out the Express docs.
π‘ Tip: As req.query
βs shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting.
app.get('/api/v1/query', (req, res) => {
const { search, limit } = req.query;
const products = search ? data.products.filter(product => product.name.startsWith(search)) : data.products;
const limitedProducts = limit ? products.slice(0, Number(limit)) : products;
return res.json(limitedProducts);
});
Middlewares
Check out the Express docs.
π‘ Tip: If the current middleware function does not end the request-response cycle, it must call next()
to pass control to the next middleware function. Otherwise, the request will be left hanging.
const logger = (req, res, next) => {
const method = req.method;
const url = req.url;
const time = new Date().getFullYear();
console.log(method, url, time);
next();
};
app.get('/', logger, (req, res) => {
res.send('Home');
});
app.get('/about', logger, (req, res) => {
res.send('About');
});
app.get('/api', [logger, authorize], (req, res) => {
res.send('API');
});
π‘ Tip: To use a particular middleware with all the routes, you can use the app.use()
method.
app.use()
Middleware
const logger = require('./logger');
const authorize = require('./authorize');
app.use([logger, authorize]);
app.get('/', (req, res) => {
res.send('Home');
});
app.use('/api', logger);
app.use('/api/products', [logger, authorize]);
const authorize = (req, res, next) => {
const { user } = req.query;
if (user === 'john') {
req.user = { name: 'john', id: 3 };
next();
} else {
res.send('Unauthorized');
}
};
module.exports = authorize;
Commonly Used Express Middlewares
// Serve static files
app.use(express.static('/public'));
// Parse data from forms
app.use(express.urlencoded({ extended: false }));
// Parse JSON payloads
app.use(express.json());
// Cookie-parser β Parse cookies
app.use(cookieParser());
π‘ Tip: Difference between a node module and Express middleware?
A node module is a reusable block of code that can be imported and used in a Node.js application. Express middleware is a specific type of node module that intercepts incoming HTTP requests and provides additional functionality to the application, such as parsing request data or handling authentication.
π Recommended Reads:
HTTP Methods
const express = require('express');
const app = express();
let { people }
= require('./data');
app.use(express.static('./methods-public'));
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.get('/api/people', (req, res) => {
res.status(200).json({ success: true, data: people });
});
app.post('/api/people', (req, res) => {
const { name } = req.body;
if (!name) {
return res.status(400).json({ success: false, msg: 'please provide name value' });
}
res.status(201).json({ success: true, person: name });
});
app.put('/api/people/:id', (req, res) => {
const { id } = req.params;
const { name } = req.body;
const person = people.find((person) => person.id === Number(id));
if (!person) {
return res.status(404).json({ success: false, msg: `no person with id ${id}` });
}
const newPeople = people.map((person) => {
if (person.id === Number(id)) {
person.name = name;
}
return person;
});
res.status(200).json({ success: true, data: newPeople });
});
app.delete('/api/people/:id', (req, res) => {
const person = people.find((person) => person.id === Number(req.params.id));
if (!person) {
return res.status(404).json({ success: false, msg: `no person with id ${req.params.id}` });
}
const newPeople = people.filter((person) => person.id !== Number(req.params.id));
return res.status(200).json({ success: true, data: newPeople });
});
app.listen(5000, () => {
console.log('Server is listening on port 5000....');
});
Third-Party Middlewares
morgan
Use morgan middleware for logging HTTP requests
Install using
npm install morgan
const morgan = require('morgan');
app.use(morgan('tiny'));
Helmet
Use Helmet middleware for setting HTTP headers that enhance security.
Install using
npm install helmet
const helmet = require('helmet');
app.use(helmet());
CORS (Cross-Origin Resource Sharing)
Use CORS middleware for handling CORS issues in REST APIs.
Install using
npm install cors
const cors = require('cors');
app.use(cors());
Rate Limiter
Use the
express-rate-limit
package for limiting repeated requests.Install using
npm install express-rate-limit
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
});
app.use(limiter);
Express Routers
Express Routers are a way to modularize the application by separating routes into different files.
You can split routers for different parts of the application (e.g., auth routes, product routes).
const express = require('express');
const router = express.Router();
// Router-specific middleware
router.use(express.json());
router.get('/', (req, res) => {
res.send('Product Home Page');
});
router.get('/:id', (req, res) => {
res.send(`Product with ID: ${req.params.id}`);
});
module.exports = router;
Use the router in your main app:
const productRouter = require('./routes/product');
app.use('/products', productRouter);
Template Engines in Express
Handlebars
npm install express-handlebars
const express = require('express');
const exphbs = require('express-handlebars');
const app = express();
// Set up Handlebars as the template engine
app.engine('handlebars', exphbs());
app.set('view engine', 'handlebars');
app.get('/', (req, res) => {
res.render('home', { title: 'Home Page' });
});
app.listen(3000, () => {
console.log('Server is listening on port 3000....');
});
EJS
npm install ejs
const express = require('express');
const app = express();
// Set EJS as the template engine
app.set('view engine', 'ejs');
app.get('/', (req, res) => {
res.render('home', { title: 'Home Page' });
});
app.listen(3000, () => {
console.log('Server is listening on port 3000....');
});
π Recommended Reads: