PUT and DELETE HTTP methods are used to update and remove existing resources on a server, enabling full CRUD operations in RESTful APIs.
- PUT updates an existing resource by replacing or modifying its data.
- DELETE removes a resource permanently from the server.
- Both methods are idempotent, meaning repeated requests produce the same result.
PUT Request
The PUT HTTP method is used to update existing resources on a server by sending the modified data in the request body.
- Updates an existing user’s data.
- Requires a unique identifier (e.g., user ID).
- Sends updated fields in the request body.
- Returns the updated resource or a success message.
- Commonly used with servers running on localhost during development.
Update the Data
The PUT method is used to modify existing user information by sending updated data to the server.
- Updates data for a specific user using an ID.
- Sends the new values in the request body.
Example: To change the name of a user with ID 1, you can send a request like this.
{
"id": 1,
"name": "Nicol"
}
The following code snippet shows only the PUT logic inside an HTTP server.
if (req.method === "PUT") {
let data = "";
req.on("data", (chunk) => {
data += chunk;
});
req.on("end", () => {
let body;
try {
body = JSON.parse(data);
} catch {
res.statusCode = 400;
return res.end(JSON.stringify({ message: "Invalid JSON" }));
}
if (!body.id || !body.name) {
res.statusCode = 400;
return res.end(JSON.stringify({ message: "Missing id or name" }));
}
const user = users.find((u) => u.id === body.id);
if (!user) {
res.statusCode = 404;
return res.end(JSON.stringify({ message: "User not found" }));
}
user.name = body.name;
res.statusCode = 200;
res.end(JSON.stringify({ user }));
});
}
- This request will update the name of the user with ID 1 in the database.
- If the user is found, their name is updated with the new name from the request.
DELETE Request
The DELETE method is used to remove an existing user from the server.
- Identifies the user using a unique ID.
- Removes the user from the users array permanently.
The following code snippet shows only the DELETE logic inside an HTTP server.
if (req.method === "DELETE") {
let data = "";
req.on("data", (chunk) => {
data += chunk;
});
req.on("end", () => {
let body;
try {
body = JSON.parse(data);
} catch {
res.statusCode = 400;
return res.end(JSON.stringify({ message: "Invalid JSON" }));
}
if (!body.id) {
res.statusCode = 400;
return res.end(JSON.stringify({ message: "Missing user id" }));
}
const index = users.findIndex((u) => u.id === body.id);
if (index === -1) {
res.statusCode = 404;
return res.end(JSON.stringify({ message: "User not found" }));
}
users.splice(index, 1);
res.statusCode = 204;
res.end();
});
}
- After the DELETE request is sent, the user is removed from the users list, and a confirmation message is returned.
- Status code 204 indicates successful deletion with no response body.
Setup the Server
We are using a Node.js server running on localhost:3000. Here is the complete server.js file.
const http = require("http");
const users = [
{ id: 1, name: "Nicol" },
{ id: 2, name: "James" },
{ id: 3, name: "Marry" }
];
const server = http.createServer((req, res) => {
res.setHeader("Content-Type", "application/json");
// GET: Fetch all users
if (req.method === "GET") {
return res.end(JSON.stringify({ users }));
}
// POST: Fetch user by ID (demo purpose)
else if (req.method === "POST") {
let data = "";
req.on("data", (chunk) => {
data += chunk;
});
req.on("end", () => {
let body;
try {
body = JSON.parse(data);
} catch {
res.statusCode = 400;
return res.end(JSON.stringify({ message: "Invalid JSON" }));
}
if (!body.id) {
res.statusCode = 400;
return res.end(JSON.stringify({ message: "Missing user id" }));
}
const user = users.find((u) => u.id === body.id);
if (!user) {
res.statusCode = 404;
return res.end(JSON.stringify({ message: "User not found" }));
}
res.statusCode = 200;
res.end(JSON.stringify({ user }));
});
}
// PUT: Update user name by ID
else if (req.method === "PUT") {
let data = "";
req.on("data", (chunk) => {
data += chunk;
});
req.on("end", () => {
let body;
try {
body = JSON.parse(data);
} catch {
res.statusCode = 400;
return res.end(JSON.stringify({ message: "Invalid JSON" }));
}
if (!body.id || !body.name) {
res.statusCode = 400;
return res.end(JSON.stringify({ message: "Missing id or name" }));
}
const user = users.find((u) => u.id === body.id);
if (!user) {
res.statusCode = 404;
return res.end(JSON.stringify({ message: "User not found" }));
}
user.name = body.name;
res.statusCode = 200;
res.end(JSON.stringify({ user }));
});
}
// DELETE: Remove user by ID
else if (req.method === "DELETE") {
let data = "";
req.on("data", (chunk) => {
data += chunk;
});
req.on("end", () => {
let body;
try {
body = JSON.parse(data);
} catch {
res.statusCode = 400;
return res.end(JSON.stringify({ message: "Invalid JSON" }));
}
if (!body.id) {
res.statusCode = 400;
return res.end(JSON.stringify({ message: "Missing user id" }));
}
const index = users.findIndex((u) => u.id === body.id);
if (index === -1) {
res.statusCode = 404;
return res.end(JSON.stringify({ message: "User not found" }));
}
users.splice(index, 1);
res.statusCode = 204;
res.end();
});
}
// Unsupported methods
else {
res.statusCode = 405;
res.end(JSON.stringify({ message: "Method Not Allowed" }));
}
});
server.listen(3000, () => {
console.log("Server is running on port 3000");
});
Note: POST is used here only for demonstration but in REST APIs, GET is preferred for fetching resources.
Stateless Design in REST APIs
REST APIs follow a stateless architecture, where each client request is processed independently without relying on stored session data.
- Each request contains all required information.
- The server does not maintain client state.
- Application state is stored in the database, not in memory.