Dev.to WebDev 🛠 Dev 👁 0 📖 10 min read

Networking Essentials for Software Engineers – Part 4: Everything You Need to Know About HTTP

When we build an application, we often write code like this: const response = await fetch("https://api.example.com/users"); We know this makes a request to our backend server. But how does the server understand

Networking Essentials for Software Engineers – Part 4: Everything You Need to Know About HTTP

When we build an application, we often write code like this:

const response = await fetch("https://api.example.com/users");

We know this makes a request to our backend server. But how does the server understand what our application is requesting?

Both our application and the server need to follow the same set of rules to communicate. Otherwise, they wouldn't understand each other's requests and responses.

These rules are defined by HTTP (Hypertext Transfer Protocol).

Since we're using HTTP while building our application and communicating with the server, it comes under the Application Layer of the networking model, which we learned about earlier.

HTTP Request and Response

In our earlier example, the browser sends an HTTP request to our backend server, asking for the users' data.

The server receives the request, processes it, and sends back an HTTP response containing the result.

This communication is called the Request-Response cycle.

So, there are two parts:

  • HTTP Request: The information our application sends to the server.
  • HTTP Response: The information the server sends back to our application.

Now, let's understand what an HTTP request contains.

HTTP Request

1. HTTP Methods

When we build an application , we often make API requests to fetch, create, update, or delete data.

We use different HTTP methods depending on what we want the server to do.

Let's take an application that manages users as an example.

  • GET: Suppose we want to display all the users in our application. We use GET to fetch the list of users from the backend.

  • POST: Suppose someone fills out a registration form and clicks Submit. We use POST to send their details to the backend to create a new user.

  • PUT: Suppose we want to replace a user's existing profile details with new details. We use PUT to send the complete updated profile.

  • PATCH: Suppose we only want to change a user's city without updating the other details. We use PATCH to send just that change.

  • DELETE: Suppose a user wants to delete their account. We use DELETE to request that the backend delete it.

For example, in JavaScript, we can specify the HTTP method like this:

fetch("/api/users", {
  method: "POST"
});

These are the HTTP methods we commonly use while building applications.

2. Request URL

When we make an HTTP request, we need to tell the server which resource we want to access.

For example, while building an application in JavaScript, we might write:

fetch("https://api.example.com/users/123", {
  method: "GET"
});

Here, we're making a GET request to an API that returns the details of the user with ID 123.

Let's look at the URL:

  • https:// — The protocol used to communicate securely with the server.
  • api.example.com — The domain name of the server we're contacting.
  • /users/123 — The API path that identifies the user whose ID is 123.

Sometimes, we also pass additional information through query parameters.

For example, suppose we want to fetch only active users from Hyderabad:

fetch("https://api.example.com/users?city=Hyderabad&status=active", {
  method: "GET"
});

Here, city and status are query parameters. The backend can use them to filter the results.

So, the URL tells our application where to send the request and which resource we're asking for.

3. Request Headers

Sometimes, along with our request, we need to send some additional information to the backend. For example, what type of data we're sending or information the backend needs to check whether we're logged in.

We can send these details through HTTP headers.

For example:

fetch("https://api.example.com/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer your_access_token"
  },
  body: JSON.stringify({
    name: "Anusha",
    city: "Hyderabad"
  })
});

If you look at the headers section, we've added two things.

First, Content-Type is set to application/json because we're sending the user's details as JSON. This helps the backend understand how to read that data. If we're uploading a file, we might use a different format, such as multipart/form-data.

Now, what about Authorization?

Think about what happens when we log in to an application. After logging in, we might open our profile, view our orders, or access other pages. We don't enter our username and password every time, right?

That's because, after a successful login, the backend can give us an access token. Our application sends that token in the Authorization header with subsequent requests, allowing the backend to verify that we're already authenticated.

This is just one way of handling login. Some applications use cookies and sessions instead, where the browser automatically sends a cookie containing a session ID through the Cookie header.

Apart from these, there are many other HTTP headers. Some are added by us when needed, while browsers handle others automatically.

4. Request Body

Suppose we're building an application where users can register.

When someone fills out the registration form and clicks Submit, we need to send their details, such as their name, email, and city, to the backend.

We send this information through the HTTP request body.

For example:

fetch("https://api.example.com/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    name: "Anusha",
    email: "[email protected]",
    city: "Hyderabad"
  })
});

Here, we're making a POST request to create a new user.

If you look at the body section, we're sending the user's details as JSON. The backend receives this data and can use it to create the user.

A request body isn't always required. For example, in our earlier GET request to fetch user 123, we didn't send a body. We simply included the user ID in the URL, which was enough for the backend to know whose details we wanted.

HTTP Response

Now that we've seen what an HTTP request contains, let's look at what happens when the backend sends a response.

Suppose we make a GET request to fetch the details of user 123. The backend receives the request, looks for that user, and sends back a response.

An HTTP response mainly contains three things:

  • Status Code: Tells us whether the request was successful or something went wrong.
  • Response Headers: Provide additional information about the response, such as the format of the data being returned.
  • Response Body: Contains the actual data returned by the backend.

1. HTTP Status Codes

If the backend finds user 123, it might return 200 OK. But if the user doesn't exist, it might return 404 Not Found instead.

These numbers are called HTTP status codes, and they help us understand what happened to our request.

Here are some common status codes we come across while building applications:

Status Code What it means
200 OK The request was successful.
201 Created Something new, like a user, was created successfully.
400 Bad Request There's something wrong with the request we sent.
401 Unauthorized We need to log in or provide valid authentication.
403 Forbidden We're not allowed to access what we requested.
404 Not Found The resource we're looking for doesn't exist or couldn't be found.
500 Internal Server Error Something went wrong on the backend while processing our request.

You might have noticed that some status codes start with 2, others with 4 or 5.

HTTP status codes are divided into five groups:

  • 1xx: Informational responses
  • 2xx: Successful requests
  • 3xx: Redirections
  • 4xx: Client errors
  • 5xx: Server errors

For example, when we see a 2xx status code, our request was successful. If we see 4xx, there's usually an issue with the request or access permissions. And 5xx means something went wrong on the server's side.

2. Response Headers

Just like HTTP requests, responses also contain headers.

Along with the result, the backend might send headers like these:

Content-Type: application/json

Here, Content-Type is application/json because the backend is returning the user's details in JSON format. If it were sending an HTML page, the content type would be text/html.

Another header is Content-Length, which tells us the size of the response body in bytes when the server includes it.

There's also a header called Set-Cookie. Suppose we log in to an application. The backend might send a session ID through this header, and the browser stores it as a cookie. When we make another request, the browser sends that cookie back, so the backend can recognize us without asking us to log in again.

These are some common response headers. The backend can send other headers depending on what it's returning.

3. Response Body

If the backend finds user 123, the response body might look like this:

{
  "id": 123,
  "name": "Anusha",
  "email": "[email protected]",
  "city": "Hyderabad"
}

Here, the response body contains the actual user details returned by the backend.

The response body doesn't always contain JSON. Depending on what we're requesting, the backend might return HTML, plain text, images, or other types of data.

Also, not every HTTP response has a body. For example, suppose we send a DELETE request to remove user 123. Once the backend successfully deletes the user, it might return 204 No Content, which means the request was successful, but there's no data in the response body.

HTTP is Stateless

Suppose we log in to an application and then open our profile page.

The login request was successful, but when we make another request to view our profile, HTTP doesn't automatically remember that we logged in earlier.

That's because HTTP is a stateless protocol. Each request is treated independently, and the server doesn't automatically remember what happened in previous requests.

But when we use applications, we don't have to log in every time we open a new page, right?

Applications handle this using things like cookies, sessions, or access tokens.

For example, after logging in, the backend might create a session and send its ID to our browser as a cookie. When we make another request, the browser sends that cookie back, allowing the backend to identify us.

So, even though HTTP itself is stateless, applications can still remember logged-in users by using these mechanisms.

HTTP vs HTTPS

You might have noticed that some website URLs start with http://, while most websites today use https://.

With HTTP, the information we send travels without encryption, meaning someone who intercepts it might be able to read it.

Remember our school days? Sometimes, when we wanted to talk to our friends without others understanding, we'd make up our own secret language. We'd add extra letters between words or change them in a way only we understood.

HTTPS works on a similar idea, but uses much stronger protection. It encrypts the information exchanged between our browser and the server, making it unreadable to anyone intercepting it.

HTTPS also helps protect the information from being changed along the way and verifies that we're communicating with the intended website.

We'll learn how this protection actually works later in our networking series.

HTTP Versions

HTTP has been around for many years, and it has gone through several versions to make communication between browsers and servers faster and more efficient.

Let's look at how it evolved.

HTTP/1.0

HTTP/1.0 uses TCP to communicate between the browser and the server.

In this version, a new TCP connection was typically created for each request.

Imagine opening a website that contains an HTML page, 10 images, and a few other files. The browser would usually need to open a separate connection for each request.

Creating connections repeatedly added extra time.

HTTP/1.1

HTTP/1.1 also uses TCP, but it improved how connections were handled.

Instead of opening a new TCP connection for every request, the browser could reuse the same connection for multiple requests.

This reduced the time spent creating new connections.

HTTP/2

HTTP/2 still uses TCP in its usual web deployment, but it introduced an important improvement called multiplexing.

Suppose a website needs to load 10 images. With HTTP/2, the browser can send multiple requests and receive their responses over the same TCP connection without waiting for each response to finish before starting the next.

This made loading websites more efficient.

HTTP/3

HTTP/3 takes a different approach. Instead of TCP, it uses a newer transport protocol called QUIC, which works over UDP.

QUIC allows multiple requests to share a connection while reducing delays caused by lost packets. It can also handle network changes, such as switching from Wi-Fi to mobile data, more smoothly.

The HTTP methods, status codes, headers, and request-response concepts we've learned remain largely the same across these versions. What changes is how HTTP sends and receives information over the network.

We'll learn more about TCP, UDP, and QUIC when we cover transport-layer protocols later in our networking series.

Viewing HTTP Requests and Responses in the Browser

We can actually see the HTTP requests and responses we've discussed using our browser.

Let's try it in Google Chrome.

  1. Open any website, right-click anywhere on the page, and select Inspect.
  2. Go to the Network tab and refresh the page.
  3. Click on any request to see its URL, method, status code, headers, and response.
  4. To check the HTTP version, right-click the Name column heading and enable Protocol.

You'll see the HTTP version used for each request:

  • http/1.1 — HTTP/1.1
  • h2 — HTTP/2
  • h3 — HTTP/3

You might even notice different HTTP versions being used on the same webpage, depending on which servers the browser is communicating with.

If you're just starting to learn networking, I hope this article helped you understand HTTP a little better.

Some of these concepts might already be familiar if you're building applications every day, but topics like HTTP versions and how they've evolved might be new to you.

Thanks for reading! See you in the next part of the Networking Essentials series.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.