KAHIBARO
Discord Login Register

1.5. Request-Response Cycle

Overview

When you use a website or an API, your browser or app sends a request to a server and then waits for a response. This back‑and‑forth is called the request‑response cycle. Understanding this cycle is one of the most important foundations for backend development, because everything your backend code does is triggered by a request and ends with a response.

In this chapter you will see what happens in that cycle, step by step, with concrete examples that will help you relate it to your own browsing experience and to backend code you will write later.

The Basic Flow

At its simplest, the request‑response cycle looks like this:

  1. A client wants something.
  2. The client sends an HTTP request to a server.
  3. The server receives the request, processes it, and may talk to databases or other services.
  4. The server prepares an HTTP response.
  5. The server sends the response back to the client.
  6. The client receives the response and uses it, for example by rendering a page or updating the screen.

You will learn the detailed networking pieces like TCP, ports, and HTTP structure in later chapters. Here we stay at the level that matters to a backend developer who is designing and implementing server logic.

Who Is the Client, Who Is the Server?

The client is usually a web browser, a mobile app, or another backend service that wants data or an action to be performed.

The server is your backend application that listens for requests and responds to them.

In a simple example:

From a backend developer’s point of view, the client is anything that speaks HTTP to your server. It does not matter whether it is a browser, an Android app, or another API. You handle all of them through the same request‑response pattern.

A Simple Real‑World Example

Imagine you visit a blog at:

https://myblog.com/posts/42

You want to read the blog post with ID 42. This is what happens in the request‑response cycle in simplified form.

  1. You type the URL and press Enter.
  2. Your browser prepares an HTTP GET request to /posts/42 on the host myblog.com.
  3. The request travels across the network to the server that hosts myblog.com.
  4. The backend application running there receives the request and looks at:
    • the path /posts/42
    • the method GET
    • maybe some cookies or headers for authentication
  5. The backend code sees that this URL matches a “get post by id” route, for example GET /posts/{id}.
  6. The code queries the database: “Give me the post with ID 42.”
  7. The database returns the stored data for that post.
  8. The backend renders an HTML page that contains the title and content of the post.
  9. The backend sends an HTTP response with:
    • a status code, for example 200 OK
    • headers describing the content type
    • the HTML page as the body of the response
  10. Your browser receives the response, parses the HTML, and shows the blog post on your screen.

This whole story is one request‑response cycle. You clicked one URL; the server handled one request and returned one response.

If you then click “Next post,” that is a new request‑response cycle. Every time the browser or app “talks” to the server, a new cycle starts.

Structure of a Request in the Cycle

Each request in the cycle contains several important parts that your backend code can use:

Later chapters will go deep into each of those pieces, but here it is important to connect them to the cycle: the server receives the request as a structured object that your code can inspect.

For example, when a client sends this request:

http
GET /users/5 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer <token>

your backend framework will present it to your code as something like:

Your route handler will then decide what to do based on this information.

Structure of a Response in the Cycle

The response has three main parts:

For example, the server might respond to GET /users/5 with:

http
HTTP/1.1 200 OK
Content-Type: application/json
{
  "id": 5,
  "name": "Alice",
  "email": "alice@example.com"
}

Your backend code is responsible for choosing the correct status code, setting the right headers, and generating the body that the client expects.

A backend application must always return a valid HTTP response for every request it accepts. At a minimum this means:

  • a status code,
  • optional headers,
  • and optionally a response body.

Step‑by‑Step: Login Request‑Response Cycle

Consider a typical login form. You open https://example.com/login. That first page load is already one request‑response cycle:

  1. Browser sends GET /login.
  2. Server responds with an HTML login page that includes a form with username and password fields.

Now you fill in the form and click “Login.” That triggers another cycle.

  1. The browser reads the form and sends something like:
http
   POST /login HTTP/1.1
   Host: example.com
   Content-Type: application/x-www-form-urlencoded
   username=alice&password=secret123
  1. The server receives the POST request and passes it to the part of the code that handles /login with the POST method.
  2. The backend reads the form data from the request body.
  3. The backend checks the credentials against the database.
  4. If the credentials are correct:
    • it might create a session record in the database or memory,
    • it might generate a session ID,
    • it returns a redirect to /dashboard and sets a session cookie.
  5. If the credentials are wrong:
    • it returns a response that contains the login page again
    • plus an error message like “Invalid username or password.”

From the browser’s viewpoint, every login attempt is one independent request‑response cycle. From your backend’s viewpoint, each attempt is one independent call to your login handler.

From URL to Backend Code

Most backend frameworks, including those you will use later, follow a pattern like this in each request‑response cycle:

  1. A low‑level web server (for example Uvicorn or Gunicorn) listens for incoming HTTP requests.
  2. When a request arrives, the server parses it into a request object and hands it to your framework (for example FastAPI).
  3. The framework matches the request to a route, for example:
    • GET /posts → function list_posts
    • POST /posts → function create_post
    • GET /posts/{id} → function get_post
  4. It then calls the appropriate function, passing the request data as parameters.
  5. Your function runs your business logic. It might:
    • validate input,
    • query or update the database,
    • talk to other APIs,
    • prepare the data for the client.
  6. Your function returns some result object, usually including:
    • a status code,
    • a body (string, dictionary, etc.),
    • maybe headers.
  7. The framework converts that result into a proper HTTP response.
  8. The web server sends that HTTP response back over the network to the client.

As a backend developer you mainly write the code in step 5 and define the mapping in step 3. The rest is handled by the framework and the web server, but all of it exists to support the request‑response cycle.

Multiple Requests, Not a Continuous Conversation

It may feel like you have a continuous conversation with a website, but the web is built around many separate request‑response cycles. Each page load, button click, or API call is a new request that does not automatically “remember” previous ones.

To maintain continuity, the backend uses tools like cookies, sessions, and tokens, which you will learn about later. However, each HTTP request itself is independent.

For example, in an online store:

From the user’s point of view this is one flow: “I shopped and paid.” From the backend’s point of view this is a sequence of request‑response cycles that share state through identifiers like session IDs or user IDs.

Synchronous vs Asynchronous Feeling

The request‑response cycle is usually synchronous from the client’s perspective: the client sends a request and waits for the response. During this time the client might show a loading spinner.

However, modern applications sometimes want to feel more “live.” They still use the request‑response cycle, but often in smaller pieces:

Each of those background calls is still a complete HTTP request‑response cycle. There is just no full page reload, and the browser or app decides how to use the response.

Errors in the Request‑Response Cycle

Not every request ends with a successful response. Sometimes the server cannot fulfill the request, or the client sent something invalid.

Typical error cases include:

From the viewpoint of the cycle, this is still a normal response. The server received a request and replied with a valid HTTP response, just with an error code and possibly an error message in the body.

From the client’s point of view, an HTTP error such as 404 or 500 is still a successful completion of the request‑response cycle. The request reached the server, and the server responded. The error is part of the response, not a failure to complete the cycle.

Idempotent and Non‑Idempotent Cycles

This idea is important when you think about what happens if a request is sent twice by mistake, for example because of a network retry.

Some requests are safe to repeat:

Other requests change state:

The request‑response cycle is always “one request, one response,” but as a backend developer you must keep in mind what happens if a client repeats the cycle by sending the same request again. This is closely tied to how you use HTTP methods, which you will cover in detail later.

How the Cycle Looks in Code (Preview)

In a Python backend using a modern framework, a route handler function usually corresponds to one request‑response cycle. When a request matches that route, the framework calls your function once, and whatever you return becomes the response.

Here is a very simplified example in a FastAPI style:

python
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello")
def say_hello():
    return {"message": "Hello, world!"}

For each request that a client sends to GET /hello, the following happens:

  1. FastAPI receives the HTTP request from the web server.
  2. It recognizes that the path /hello with method GET should call say_hello.
  3. It calls say_hello() once, for this one request.
  4. The function returns a Python dictionary.
  5. FastAPI converts that dictionary into a JSON response with status code 200.
  6. The web server sends the response back to the client.

If 100 users hit /hello at nearly the same time, say_hello will be called around 100 separate times, once per request‑response cycle.

Thinking Like a Backend Developer

When you design and write backend code, try to think in terms of request‑response cycles:

If you can clearly describe the life of a single request from the moment it arrives until the moment a response leaves the server, you are already thinking like a backend developer.

Later chapters will fill in the technical details about HTTP, headers, cookies, sessions, APIs, and frameworks. The common foundation for all of them is the same simple pattern: a client sends a request, your backend processes it, and your backend sends a response.

Views: 11

Comments

Please login to add a comment.

Don't have an account? Register now!