Have you ever wondered what actually happens when you click a button on a website and data appears on the screen?
For example, you open an e-commerce website and click "View Products".
Behind the scenes, your frontend might send a request like:
GET /api/products
The backend receives this request, processes it, may communicate with a database, and finally sends a response back.
But how does this actually work?
What is inside an HTTP request?
What are headers?
What is the difference between GET, POST, PUT, and DELETE?
What are query parameters and URL parameters?
And how does all of this connect to a MERN application?
Let's understand HTTP requests step by step.
1. What is HTTP?
HTTP stands for HyperText Transfer Protocol.
It is a protocol that allows clients and servers to communicate with each other over a network.
A client can be:
- Web browser
- React application
- Mobile application
- API testing tool
- Another server
A server can be:
- Node.js server
- Express server
- Java backend
- Python backend
- Any application that can handle HTTP requests
The basic communication looks like this:
Client
|
| HTTP Request
↓
Server
|
| HTTP Response
↓
Client
The client asks for something, and the server responds.
This is called the request-response model.
2. A Simple HTTP Request
Suppose we have an API for getting products.
The client sends:
GET /api/products HTTP/1.1
Host: example.com
Accept: application/json
The server might respond:
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"id": 1,
"name": "Keyboard",
"price": 2000
}
]
There are several important parts here.
The request contains:
HTTP Method
URL / Path
Headers
Body
The response contains:
Status Code
Headers
Body
Let's understand each part.
3. Anatomy of an HTTP Request
An HTTP request can contain four important parts:
Method
URL
Headers
Body
For example:
POST /api/products HTTP/1.1
Host: example.com
Content-Type: application/json
Authorization: Bearer token123
{
"name": "Keyboard",
"price": 2000
}
Let's break it down.
Method
POST
This tells the server what operation the client wants to perform.
URL / Path
/api/products
This tells the server which resource the client wants to access.
Headers
Content-Type: application/json
Authorization: Bearer token123
Headers provide additional information about the request.
Body
{
"name": "Keyboard",
"price": 2000
}
The body contains the actual data being sent to the server.
4. HTTP Methods
HTTP methods tell the server what the client wants to do.
The most commonly used methods are:
| Method | Purpose | Example |
|---|---|---|
| GET | Read data | Get products |
| POST | Create data | Create a product |
| PUT | Replace/update data | Replace a product |
| PATCH | Partially update data | Update product price |
| DELETE | Delete data | Delete a product |
Let's understand them one by one.
GET
GET is used to retrieve data.
Example:
GET /api/products
Express:
app.get("/api/products", (req, res) => {
res.json({
message: "Products fetched successfully"
});
});
The server returns the requested data.
POST
POST is generally used to create new data.
Example:
POST /api/products
The client can send product information in the request body:
{
"name": "Keyboard",
"price": 2000
}
Express:
app.post("/api/products", (req, res) => {
res.status(201).json({
message: "Product created successfully"
});
});
PUT
PUT is generally used to replace an existing resource.
Example:
PUT /api/products/10
The client may send the complete updated resource.
{
"name": "Mechanical Keyboard",
"price": 3500
}
PATCH
PATCH is generally used to partially update a resource.
For example, if we only want to change the price:
PATCH /api/products/10
Body:
{
"price": 3500
}
We don't need to send the entire product.
DELETE
DELETE is used to delete a resource.
Example:
DELETE /api/products/10
Express:
app.delete("/api/products/:id", (req, res) => {
res.json({
message: "Product deleted successfully"
});
});
5. GET vs POST
One of the most common questions when learning backend development is:
What is the difference between GET and POST?
GET
Used to retrieve data.
GET /api/products
POST
Used to send data to the server, commonly to create a resource.
POST /api/products
For example:
{
"name": "Keyboard",
"price": 2000
}
A simple way to remember:
GET → Give me data
POST → Here is some data
6. What are HTTP Headers?
Headers provide additional information about an HTTP request or response.
For example:
Content-Type: application/json
Authorization: Bearer token123
Accept: application/json
Headers follow this format:
Name: Value
For example:
Content-Type: application/json
means that the content being sent is JSON.
7. Important HTTP Headers
There are many HTTP headers, but some are especially important for web developers.
Content-Type
Tells the server what type of data is being sent.
Content-Type: application/json
For example:
{
"name": "Keyboard"
}
Accept
Tells the server what type of response the client expects.
Accept: application/json
Authorization
Commonly used for authentication.
Authorization: Bearer token123
We will explore authentication and JWT in later parts of this series.
Cookie
Cookies can be sent from the browser to the server.
Cookie: sessionId=abc123
Cookies are commonly used for sessions, authentication, preferences, and other browser-related data.
Cache-Control
Used to control caching behavior.
Cache-Control: max-age=3600
We will discuss caching in a later part of this series.
8. What is the Request Body?
The request body contains data sent from the client to the server.
For example, when creating a product:
POST /api/products
Content-Type: application/json
{
"name": "Mechanical Keyboard",
"price": 3500
}
The JSON object is the request body.
In Express, we can access it using:
req.body
First, we need to enable JSON parsing:
const express = require("express");
const app = express();
app.use(express.json());
app.post("/api/products", (req, res) => {
console.log(req.body);
res.json({
message: "Product received"
});
});
If the client sends:
{
"name": "Mechanical Keyboard",
"price": 3500
}
then:
req.body
contains:
{
name: "Mechanical Keyboard",
price: 3500
}
9. Query Parameters
Query parameters are values added to the URL.
For example:
/api/products?category=keyboard
Here:
category=keyboard
is a query parameter.
We can have multiple query parameters:
/api/products?category=keyboard&sort=price
In Express:
app.get("/api/products", (req, res) => {
console.log(req.query);
res.json(req.query);
});
For:
/api/products?category=keyboard&sort=price
we get:
{
category: "keyboard",
sort: "price"
}
Query parameters are commonly used for:
- Searching
- Filtering
- Sorting
- Pagination
For example:
/api/products?search=keyboard
or:
/api/products?page=2&limit=10
10. URL Parameters
URL parameters are values included directly in the URL path.
For example:
/api/products/123
Here:
123
can represent the product ID.
In Express:
app.get("/api/products/:id", (req, res) => {
console.log(req.params.id);
res.json({
productId: req.params.id
});
});
If we request:
/api/products/123
then:
req.params.id
will contain:
123
URL parameters are commonly used when accessing a specific resource.
11. Query Parameters vs URL Parameters vs Request Body
These three concepts are commonly confused when learning backend development.
Query Parameter
/api/products?category=keyboard
Used for:
Filtering
Searching
Sorting
Pagination
Access using:
req.query
URL Parameter
/api/products/123
Used to identify a specific resource.
Access using:
req.params
Request Body
{
"name": "Keyboard",
"price": 2000
}
Used to send data to the server.
Access using:
req.body
A simple way to remember:
Query Parameter → Filter or modify the request
URL Parameter → Identify a resource
Request Body → Send data
12. HTTP Status Codes
After processing the request, the server sends a response.
One important part of the response is the HTTP status code.
For example:
HTTP/1.1 200 OK
Here:
200
is the status code.
HTTP status codes are divided into five categories:
1xx → Informational
2xx → Success
3xx → Redirection
4xx → Client Error
5xx → Server Error
You don't need to memorize every status code.
Let's look at the important ones.
13. Common 2xx Status Codes
200 OK
The request was successful.
res.status(200).json({
message: "Products fetched successfully"
});
201 Created
A new resource was successfully created.
res.status(201).json({
message: "Product created successfully"
});
This is commonly used after a successful POST request.
204 No Content
The request was successful, but the server does not return a response body.
It can be useful when an operation succeeds but there is nothing to return.
14. Common 4xx Status Codes
These usually indicate a problem with the client's request.
400 Bad Request
The request is invalid.
res.status(400).json({
message: "Invalid product data"
});
401 Unauthorized
Authentication credentials are missing or invalid.
res.status(401).json({
message: "Authentication required"
});
403 Forbidden
The server understands the request, but the user does not have permission.
For example:
Normal User
↓
Admin-only resource
↓
403 Forbidden
404 Not Found
The requested resource does not exist.
For example:
GET /api/products/999
If product 999 doesn't exist:
res.status(404).json({
message: "Product not found"
});
15. Common Server Error Status Codes
These indicate that something went wrong on the server.
500 Internal Server Error
Something unexpected happened while processing the request.
res.status(500).json({
message: "Internal server error"
});
A simple way to remember:
4xx → Problem with the request
5xx → Problem on the server
16. What Does an HTTP Response Look Like?
An HTTP response can contain:
Status Code
Headers
Body
Example:
HTTP/1.1 200 OK
Content-Type: application/json
{
"message": "Products fetched successfully"
}
Here:
200 OK
is the status code.
Content-Type: application/json
is a response header.
And:
{
"message": "Products fetched successfully"
}
is the response body.
17. HTTP and JSON
Modern web applications commonly use JSON to exchange data.
JSON stands for:
JavaScript Object Notation
Example:
{
"id": 1,
"name": "Keyboard",
"price": 2000
}
An Express server can send JSON using:
res.json({
id: 1,
name: "Keyboard",
price: 2000
});
The frontend can then read the response.
const response = await fetch("/api/products");
const data = await response.json();
console.log(data);
18. Sending HTTP Requests with JavaScript
The browser provides the fetch() API for making HTTP requests.
For example:
const response = await fetch("/api/products");
const data = await response.json();
console.log(data);
The flow is:
JavaScript
↓
fetch()
↓
HTTP Request
↓
Server
↓
HTTP Response
↓
response.json()
↓
JavaScript
19. Sending Data with POST
We can also send data to the server using fetch().
const response = await fetch("/api/products", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "Keyboard",
price: 2000
})
});
const data = await response.json();
console.log(data);
Let's understand this.
Method
method: "POST"
We are sending a POST request.
Headers
headers: {
"Content-Type": "application/json"
}
We are telling the server that the request body contains JSON.
Body
body: JSON.stringify({
name: "Keyboard",
price: 2000
})
JSON.stringify() converts the JavaScript object into a JSON string that can be sent in the request body.
20. How Express Receives the Request
Now let's connect HTTP with Node.js and Express.
const express = require("express");
const app = express();
app.use(express.json());
app.post("/api/products", (req, res) => {
console.log(req.body);
res.status(201).json({
message: "Product created",
product: req.body
});
});
app.listen(3000, () => {
console.log("Server running on port 3000");
});
If the frontend sends:
{
"name": "Keyboard",
"price": 2000
}
Express receives it through:
req.body
and sends a response using:
res.json()
This is the basic connection between an HTTP request and an Express route.
21. Request → Server → Database → Response
In a real application, the server may need to communicate with a database.
For example:
app.get("/api/products", async (req, res) => {
try {
const products = await Product.find();
res.status(200).json(products);
} catch (error) {
res.status(500).json({
message: "Something went wrong"
});
}
});
The flow is:
GET /api/products
↓
Express receives request
↓
Route matches
↓
Product.find()
↓
MongoDB returns data
↓
Express creates response
↓
Client receives JSON
This is a common flow in MERN applications.
22. Complete HTTP Flow in a MERN Application
Let's look at a complete example.
Suppose a React application wants to display products.
Step 1 — React sends a request
const response = await fetch("/api/products");
const products = await response.json();
Step 2 — HTTP request is created
Conceptually:
GET /api/products HTTP/1.1
Accept: application/json
Step 3 — Express receives the request
app.get("/api/products", async (req, res) => {
Step 4 — Backend communicates with MongoDB
const products = await Product.find();
Step 5 — Server sends the response
res.status(200).json(products);
Step 6 — React receives the data
const products = await response.json();
Step 7 — React displays the data
The UI can now render the products.
The complete flow:
React
↓
fetch()
↓
HTTP GET Request
↓
Express
↓
Route
↓
Business Logic
↓
MongoDB
↓
JSON Response
↓
React
↓
UI
23. HTTP is Stateless
One important property of HTTP is that it is stateless.
Stateless means that each request is treated independently.
For example:
Request 1:
GET /api/products
Request 2:
GET /api/products/10
The second request does not automatically remember everything about the first request.
If an application needs to maintain information about a user between requests, it can use mechanisms such as:
- Cookies
- Sessions
- Tokens
- JWT
- Server-side storage
This becomes important when implementing authentication.
We will explore authentication and JWT in later parts of this series.
24. HTTP vs HTTPS
You have probably seen URLs like:
http://example.com
and:
https://example.com
HTTPS is HTTP protected using TLS.
With HTTPS, communication between the client and server is encrypted.
Conceptually:
HTTP
Client
↓
Request
↓
Server
With HTTPS:
Client
↓
Encrypted communication
↓
Server
HTTPS is important when sending sensitive information such as:
- Passwords
- Authentication tokens
- Personal information
- Payment-related information
We already discussed TLS at a high level in Part 1.
25. How Developers Debug HTTP Requests
When building frontend and backend applications, the browser's Network tab is one of the most useful debugging tools.
Open:
Browser
↓
Developer Tools
↓
Network
Then make an API request.
You can inspect:
Request URL
Request Method
Status Code
Request Headers
Request Payload
Response Headers
Response Body
For example:
Request URL:
http://localhost:3000/api/products
Request Method:
GET
Status Code:
200 OK
You can also inspect the JSON response.
This is extremely useful when debugging API problems.
26. Common HTTP Problems
404 Not Found
You may have requested the wrong endpoint.
For example, your backend has:
/api/products
but your frontend requests:
/api/product
The server may return:
404 Not Found
400 Bad Request
The request data may be invalid.
For example:
{
"price": "hello"
}
when the server expects a number.
401 Unauthorized
The request requires authentication, but valid authentication credentials were not provided.
403 Forbidden
The user is authenticated but does not have permission to access the resource.
500 Internal Server Error
Something went wrong while processing the request on the server.
When this happens, check your backend logs.
27. A Simple Mental Model for HTTP
If you're learning backend development, remember this:
HTTP REQUEST
|
+---------+----+----+---------+
| | | |
v v v v
Method URL Headers Body
| | | |
+---------+----+----+---------+
|
v
SERVER
|
v
HTTP RESPONSE
|
+-----------+-----------+
| | |
v v v
Status Code Headers Body
For example:
POST /api/products
Content-Type: application/json
{
"name": "Keyboard",
"price": 2000
}
The server processes the request and might return:
HTTP/1.1 201 Created
Content-Type: application/json
{
"message": "Product created successfully"
}
That's the basic request-response cycle.
28. A Small REST API Example
Let's combine what we have learned into a simple Express API.
const express = require("express");
const app = express();
app.use(express.json());
const products = [
{
id: 1,
name: "Keyboard",
price: 2000
},
{
id: 2,
name: "Mouse",
price: 1000
}
];
// GET all products
app.get("/api/products", (req, res) => {
res.status(200).json(products);
});
// GET one product
app.get("/api/products/:id", (req, res) => {
const id = Number(req.params.id);
const product = products.find((item) => item.id === id);
if (!product) {
return res.status(404).json({
message: "Product not found"
});
}
res.status(200).json(product);
});
// Create product
app.post("/api/products", (req, res) => {
const product = {
id: products.length + 1,
name: req.body.name,
price: req.body.price
};
products.push(product);
res.status(201).json(product);
});
// Delete product
app.delete("/api/products/:id", (req, res) => {
const id = Number(req.params.id);
const index = products.findIndex((item) => item.id === id);
if (index === -1) {
return res.status(404).json({
message: "Product not found"
});
}
products.splice(index, 1);
res.status(200).json({
message: "Product deleted successfully"
});
});
app.listen(3000, () => {
console.log("Server running on port 3000");
});
This small API demonstrates:
GETPOSTDELETE- URL parameters
- Request body
- Status codes
- JSON responses
- Express routes
29. The Big Picture
Let's put everything together.
When you click a button in a web application, something like this can happen:
USER
|
v
REACT UI
|
v
fetch()
|
v
HTTP REQUEST
|
+-----------+-----------+
| | |
v v v
Method Headers Body
| | |
v v v
POST Content-Type |
Authorization |
| | |
+-----------+-----------+
|
v
EXPRESS SERVER
|
v
ROUTE
|
v
BUSINESS LOGIC
|
v
MONGODB
|
v
SERVER RESPONSE
|
v
HTTP RESPONSE
|
v
REACT
|
v
UI UPDATE
This is the basic communication cycle behind many modern web applications.
30. What You Should Remember
You don't need to memorize every part of the HTTP specification.
Start with these concepts:
HTTP
↓
Request / Response
↓
HTTP Methods
↓
Headers
↓
Request Body
↓
Query Parameters
↓
URL Parameters
↓
Status Codes
↓
JSON
↓
REST APIs
↓
Express
For example:
GET /api/products?page=2
means:
-
GET→ retrieve data -
/api/products→ endpoint -
page=2→ query parameter
And:
POST /api/products
Content-Type: application/json
{
"name": "Keyboard",
"price": 2000
}
means:
-
POST→ send data, commonly to create a resource -
/api/products→ endpoint -
Content-Type→ request contains JSON - Request body → product data
Conclusion
HTTP is one of the fundamental building blocks of web development.
Every time your frontend communicates with your backend, HTTP is usually involved.
Once you understand:
Request
↓
Method
↓
URL
↓
Headers
↓
Body
↓
Server
↓
Response
↓
Status Code
↓
Response Body
APIs become much easier to understand and debug.
In a MERN application, the flow can look like:
React
↓
HTTP Request
↓
Node.js + Express
↓
Business Logic
↓
MongoDB
↓
HTTP Response
↓
React
Understanding this flow gives you a strong foundation for backend development.
Final Takeaway
HTTP may look simple from the outside:
Request → Response
But inside a real application, that request passes through multiple layers:
Frontend
↓
HTTP
↓
Express
↓
Business Logic
↓
Database
↓
HTTP
↓
Frontend
Once you understand this flow, you're not just using APIs anymore — you understand what is happening behind them.
References
If you want to go deeper into HTTP and web development, these are useful references:
Top comments (0)