Create a new directory for your project.
Navigate to the directory and initialize a new Node.js project by running:
npm init -y
Install Express:
npm install express
Create a file named index.js
and set up a basic Express server:
const express = require("express");
const app = express();
const port = 3000;
// Middleware to parse JSON requests
app.use(express.json());
// Basic Route
app.get("/", (req, res) => {
res.send("Welcome to the Node.js API");
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
Run the server:
node index.js
Open http://localhost:3000
in your browser or use a tool like Postman to see the welcome message.
Let's create a simple RESTful API to manage a list of todos. We'll define routes for the following operations:
GET /todos
: Get a list of all todos.GET /todos/:id
: Get a specific todo by its ID.POST /todos
: Add a new todo.PUT /todos/:id
: Update a todo by its ID.DELETE /todos/:id
: Delete a todo by its ID.In your index.js
, define the routes:
let todos = [
{ id: 1, title: "Write a blog post", author: "John Doe", is_completed: true },
{ id: 2, title: "Learn Node.js", author: "Jane Smith", is_completed: false },
];
// Get all todos
app.get("/todos", (req, res) => {
res.json(todos);
});
// Get a todo by ID
app.get("/todos/:id", (req, res) => {
const todo = todos.find((b) => b.id === parseInt(req.params.id));
if (!todo) return res.status(404).send("Todo not found");
res.json(todo);
});
// Add a new todo
app.post("/todos", (req, res) => {
const newTodo = {
id: todos.length + 1,
title: req.body.title,
author: req.body.author,
};
todos.push(newTodo);
res.status(201).json(newTodo);
});
// Update a todo by ID
app.put("/todos/:id", (req, res) => {
const todo = todos.find((b) => b.id === parseInt(req.params.id));
if (!todo) return res.status(404).send("Todo not found");
todo.title = req.body.title;
todo.author = req.body.author;
res.json(todo);
});
// Delete a todo by ID
app.delete("/todos/:id", (req, res) => {
const todoIndex = todos.findIndex((b) => b.id === parseInt(req.params.id));
if (todoIndex === -1) return res.status(404).send("Todo not found");
todos.splice(todoIndex, 1);
res.status(204).send();
});
Use a tool like Postman to test the API. Here are some example requests:
Example POST request body to add a todo:
{
"title": "Do a project",
"author": "Alice",
"is_completed": false
}
Middleware functions are functions that have access to the request object (req
), the response object (res
), and the next middleware function in the application’s request-response cycle.
In this step, we’ll add a simple logging middleware that logs the details of each request:
// Middleware to log requests
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
This middleware will log the HTTP method and URL for each incoming request.
Error-handling middleware is used to catch and handle any errors that occur during the request-response cycle.
Here’s a simple example of error-handling middleware:
// Error handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send("Something went wrong!");
});
Place this at the end of your index.js
file to ensure that it catches any errors from the other routes.
As your application grows, you’ll want to move the routes into separate modules to keep your code organized.
routes
.routes
folder, create a file named todos.js
.Move the todos routes into todos.js
:
const express = require("express");
const router = express.Router();
let todos = [
{ id: 1, title: "Write a blog post", author: "John Doe", is_completed: true },
{ id: 2, title: "Learn Node.js", author: "Jane Smith", is_completed: false },
];
router.get("/", (req, res) => {
res.json(todos);
});
router.get("/:id", (req, res) => {
const todo = todos.find((b) => b.id === parseInt(req.params.id));
if (!todo) return res.status(404).send("Todo not found");
res.json(todo);
});
router.post("/", (req, res) => {
const newTodo = {
id: todos.length + 1,
title: req.body.title,
author: req.body.author,
};
todos.push(newTodo);
res.status(201).json(newTodo);
});
router.put("/:id", (req, res) => {
const todo = todos.find((b) => b.id === parseInt(req.params.id));
if (!todo) return res.status(404).send("Todo not found");
todo.title = req.body.title;
todo.author = req.body.author;
res.json(todo);
});
router.delete("/:id", (req, res) => {
const todoIndex = todos.findIndex((b) => b.id === parseInt(req.params.id));
if (todoIndex === -1) return res.status(404).send("Todo not found");
todos.splice(todoIndex, 1);
res.status(204).send();
});
module.exports = router;
Then, in your index.js
file, require and use the routes:
const todosRouter = require("./routes/todos");
app.use("/todos", todosRouter);
Now your routes are modularized!
timestamp
field to the todo model).This lesson builds upon the basics of Node.js and Express by applying practical concepts like route handling, middleware, and modularization. By the end of this lesson, you’ll have created a fully functional RESTful API that can perform CRUD operations.