Study Notes
Spring Boot Frameworkfoundation

REST API Backend, Beneath the Hood

What every backend actually does — address vs port, anatomy of a request URL, the client → server flow, and proving it all by hand from the terminal. The plumbing underneath a Spring REST controller.

30 min read·verified Spring Boot 4.x·reviewed 2026-08-28

After this you should be able to

  • Trace an HTTP request
  • Test an endpoint with curl
Address / PortRequest Flowcurl by hand

System Design · REST APIs

What actually happens between the moment an app fires a request and the moment your server sends a response, told from the socket up: ports, listeners, TCP connections, and the raw shape of an HTTP request.

JAVA-301 · Session 2 · Updated Jul 2026 · Read ~14 min


Choose your route#

Problem: a controller makes more sense when you can trace the request beneath it. Spend 30 minutes learning the flow or 12 minutes rehearsing it.

Learning goal

Recall first: separate a machine address from a port. HTTP knowledge helps, but this page remains open if it is new.

  • Trace an HTTP request.
  • Test an endpoint with curl.
  • Diagnose a refused connection.

Shared core: requests are a sequence#

A client resolves a host, connects to an IP and port, sends an HTTP message, then the server parses, processes, and responds. Spring hides most of that loop, not its consequences.

Closest confusion: an IP identifies a machine; a port identifies the process listening on that machine. A URL path identifies neither.

Failure trace: connection refused means the network reached the machine but no process accepts that port. It is not evidence that a controller returned slowly.

Decision rule: when a request fails, test resolution, reachability, listener, HTTP shape, and application logic in that order.

Version note: the HTTP and TCP concepts are stable; Spring Boot examples were reviewed for 4.x on 2026-08-28.

Learn deeply: observe a request without the framework#

Mission (20 minutes): run a tiny Boot endpoint, use curl -v to inspect the request/response, then point curl at one wrong port. Work with the controller and your terminal.

Acceptance checks: you can label method, path, headers, status, and body; you can reproduce a refusal; you can move the server port and update the client.

  1. Call the working endpoint with verbose curl.
  2. Change only the port and record the OS error.
  3. Add one query parameter and observe how it crosses the boundary.
Solution shape, not a script

Use a one-route controller. The point is to isolate transport evidence, not build a full API.

Transfer: predict which part changes when a browser calls the same path over HTTPS through a reverse proxy.

Prepare for interviews: follow the wire#

Two-minute summary: DNS finds a host, TCP reaches an IP:port, HTTP carries application intent, and the server follows listen, parse, process, respond.

Explain in 60 seconds: why can one IP host multiple services?

Primary question: walk through a request from URL to controller. Follow-ups: what is DNS responsible for, and what distinguishes a 404 from connection refused?

Debug exercise: curl localhost:8080/users refuses while the app log says it started on 8081. Explain the evidence and the minimal fix.

Strong-answer outline

Use the sequence, distinguish transport from application status, and show one concrete diagnostic command. Do not claim a port is part of a URL path.

Timed mock: diagnose a failing local request in 90 seconds with only the URL and startup log.

Exit check#

  1. What does DNS return for a hostname?
  2. What does a port select?
  3. Which layer carries method and path?
  4. What does connection refused eliminate?
  5. What are the four universal backend jobs?

Learn next: Use trace an http request as the base, then retrieve the foundation concepts without notes in Foundation retrieval review. Interview next: Use trace an http request as the base, then map an entity in Spring Data JPA — From Object to Table.

Continue this path · Switch paths from this topic · Review first: your first endpoint

Foundation checkpoint#

Stop here before Core concepts. Answer from your own request trace, then continue only after you can diagnose the difference between a network failure and an application response.

  1. Trace a curl request from hostname through port to the controller, naming what each layer contributes.
  2. Explain why a small /ping endpoint is useful before introducing domain logic.
  3. A request is refused on port 8080. State the first two checks before changing controller code.
// the big idea

A web backend is just a program that waits at a known port, reads the raw bytes a client sends, decides what they mean, runs your logic, and writes bytes back. Everything a framework like Spring Boot does is automating those four steps, listen, parse, process, respond.

§ 1 — Notebook Summary

Notebook Summary#

Hand-copyable. Fully derivable from the detailed notes below.

The 4 things every backend does#

  • 1. Listen → wait for requests at the right port
  • 2. Parse → receive bytes, extract inputs (path, query params, body)
  • 3. Process → apply business logic
  • 4. Respond → send an appropriate response back
  • doodle: [Client] → port→ [ box: Listen→Parse→Process→Respond ] → [Client]

Address vs Port#

  • IP address → finds the machine (the mall)
  • Port → finds the service on it (the shop inside)
  • one IP → many ports → many services (8081, 8082 …)
  • doodle: 1 building icon (IP) with 4 numbered doors (ports)

The Uber request URL#

  • https:// → scheme; TLS on port 443
  • api.uber.com → host → DNS resolves to an IP
  • /api/v1/cars → path (which resource)
  • ?lat=..&long=..&status=AVAILABLE → query params = input

Client → Server flow#

  • DNS resolve host → IP
  • open TCP connection to IP:port (:443 https, :80 http)
  • send HTTP request (method + path + headers)
  • server: listen → parse → process → respond
  • doodle: URL bar → DNS cloud → IP:443 → server box → response arrow back

Prove it by hand (terminal)#

  • nc -l 8081 → start a listener on 8081
  • telnet localhost 8081 / nc localhost 8081 → connect / probe port
  • type raw request: GET /greeting HTTP/1.0 ⏎⏎
  • curl http://localhost:8081/greeting → same thing, one line

Markers#

  • ⭐ Port is a 16-bit number (0–65535); nc/telnet let you be the client or server by hand
  • ⚠ Nothing listening on a port = connection refused ("deaf ears"), not a slow reply
  • 💡 HTTP is just text over TCP — you can type a valid request yourself; blank line ends the headers

Ports to memorize#

PortUse
80HTTP
443HTTPS (TLS)
8080 / 8081local dev servers
§ 2 — Detailed Study Reference

Detailed Study Reference#

You open the Uber app and, within a second, a map fills with little cars parked around you. Nothing about that is magic, and nothing about it is only front-end. Your phone quietly reached across the internet, found one specific program running on one specific machine in a data center, handed it your coordinates, and got back a list. If any link in that chain were missing, a name that won't resolve, a door with nobody behind it, the screen would just spin. This lesson opens that chain up and looks at each link.

2.1The four jobs of any backend#

A backend server is a program whose whole life is a loop: wait for a request, answer it, wait for the next one. Strip away every framework and the job is always the same four steps, in order.

1 · Listen#

Someone has to be waiting for requests at the right port. No listener, no conversation.

2 · Parse#

Incoming bytes get received and read for their inputs: which path, which query params, what body.

3 · Process#

The business logic runs. Look up cars, check a balance, save a record.

4 · Respond#

An appropriate response is written back to the caller and the connection is closed or reused.

Analogy · the loop

Think of a cashier at a counter. They stand at one register (listen), take your order and read it back (parse), fetch the item from the back (process), and hand it over with a receipt (respond). Then they call "next". Spring Boot is a very fast cashier who never leaves the counter.

Everything that follows is really about step 1 and step 2, because they are the parts that feel invisible until you see them by hand. A framework hides them so well that many people never realize a server is "just" a program holding a port open.

2.2Reading a request URL#

A URL is a set of instructions for finding one resource on one machine and telling it what you want. Here is the exact request the Uber app makes when it asks for nearby cars.

the request
https://api.uber.com/api/v1/cars?lat=12.7&long=88.0&status=AVAILABLE

Read left to right, every piece has a job:

PieceNameWhat it does
httpsschemeUse HTTP secured with TLS. Implies port 443 unless one is stated.
api.uber.comhostA human name for a machine. DNS turns it into an IP address.
/api/v1/carspathWhich resource on that machine you want.
?lat=..&long=..query paramsThe input to the request: your location and the filter.

Before any bytes travel, two lookups happen. First, DNS resolution (the internet's phone book) turns api.uber.com into a numeric IP address. Then your phone opens an HTTPS GET request to that IP on port 443. Only now does the conversation start.

💡 tip

Query params are how a GET request carries input. They are visible in the URL, get logged, and are cached, so they suit filters and search terms, never passwords. Anything sensitive or large belongs in the request body of a POST.

2.3Address vs port: the mall and its shops#

An IP address finds the machine; a port finds the specific service running on it. Those are two different questions, and confusing them is the root of a lot of "why won't it connect" pain.

Analogy · buying jeans

You reach a shopping mall using its street address, that is the IP address, like 10.15.20.35. But the mall has many shops. Standing at the entrance shouting "I want faded blue jeans, torn in a few places" gets you nowhere, because the address only got you to the building. You still need the right shop. A port number is the shop. One mall (one IP) hosts many shops (ports 8081, 8082, 8083, 8084), each a different service.

IP 10.15.20.35 the machine (the mall) :8081 greeting-service :8082 jeans-service :8083 cart-service :8084 billing-service each port = one shop
Fig 2.3 — one IP addresses the building; ports address the services inside it.

A port is just a 16-bit number, so the range is 0 to 65535. Some are reserved by convention: 80 for HTTP, 443 for HTTPS. Local development servers usually squat on 8080 or 8081 so they don't clash with anything privileged.

⭐ trick

When a request "doesn't work," ask which of the two lookups failed. Wrong or unresolvable host is a DNS problem. Right host but nobody home on that port is a listener problem. Separating machine from service turns a vague failure into two testable questions.

2.4The full journey of a request#

From typing a URL to seeing a response, a request passes through a fixed sequence of stages. Naming them makes debugging mechanical instead of mysterious.

URL→ DNS resolve→ IP : port→ TCP connect→ HTTP request→ server→ response
Client (Uber app) DNS name → IP Server :443 listen · parse process · respond 1 resolve 2 TCP + HTTP GET /cars 3 200 OK + car list
Fig 2.4 — resolve the name, open a connection, request, respond.

Between "IP:port" and "HTTP request" sits a step people forget: the TCP connection. HTTP is a set of rules for what to say; TCP is the reliable pipe you say it through. A connection has to be established, a handshake, before a single byte of your GET line is sent. The next section makes that pipe visible.

2.5Is anyone there? Probing a port#

Before you trust a server, you can knock on its port and see if anything answers. Two small tools do this: telnet and nc (netcat). Both open a raw TCP connection to a host and port.

activity 2 · knock on 8081
telnet localhost 8081
# or
nc localhost 8081
⚠ pitfall · deaf ears

If nothing is listening on 8081, you don't get a slow or empty reply, you get connection refused immediately. The machine is up, but that shop is empty. A refused connection is a listener problem, not a network-speed problem, and chasing it as latency wastes hours.

To feel the other side, become the server yourself. Open one terminal and tell netcat to listen:

activity 3 · terminal A, be the server
nc -l 8081

Now that port has ears. In a second terminal, connect to it with telnet localhost 8081. Anything you type in one window appears in the other. You have hand-built the "listen" step of a backend with one command.

⭐ trick

The same tool plays both roles. nc -l <port> makes you the server waiting for a request; nc <host> <port> (or telnet) makes you the client sending one. Seeing both ends by hand demystifies what a framework does: it is netcat with a lot of automation bolted on top.

2.6HTTP is just text you can type#

An HTTP request is plain text sent over a TCP connection, so you can type a valid one by hand. This is the moment the abstraction cracks open. Connect to a real HTTP server and speak its language directly:

talk raw HTTP through the TCP connection
GET http://localhost:8081/greeting HTTP/1.0

You type the request line, then press Enter on a blank line to signal "headers are done". If a real HTTP server is on the other side, it replies with a status line, headers, and a body, all more text. The blank line is not decoration; it is the delimiter that tells the server the request head is finished.

💡 tip

The request line has three fixed parts: the method (GET), the path or URL, and the protocol version (HTTP/1.0). That is genuinely all a minimal GET needs. Everything else, headers, cookies, auth, is optional detail layered on the same text format.

Typing HTTP by hand is educational but tedious. curl does the whole dance, resolve, connect, send a well-formed request, print the response, in one line:

the shortcut
curl http://localhost:8081/greeting
you / curl the client TCP connection (the pipe) :8081 HTTP server → GET /greeting HTTP/1.0 (text) ← 200 OK + body (text)
Fig 2.6 — HTTP text flows both ways through one TCP pipe.

2.7Putting it together#

A working HTTP server must be listening on the right port so it can receive incoming REST API requests and process them. That single sentence is the whole lesson. The framework you will use next, Spring Boot, exists to make each of the four steps effortless.

By hand (this lesson)#

  • nc -l 8081 to listen
  • read the raw request text yourself
  • no routing, no parsing helpers
  • you write every byte back

With Spring Boot (next)#

  • embedded server listens on a configured port
  • maps /greeting to a method automatically
  • parses params and body into objects
  • serializes your return value to a response

Nothing new is happening under Spring Boot. It is the same listen, parse, process, respond loop you just performed with netcat, wrapped so you write only the business logic and let the framework hold the port.


2.8Interview & practice Q&A#

What is the difference between an IP address and a port?

An IP address identifies a machine on the network, the building. A port identifies a specific service running on that machine, the shop inside. One IP can expose many ports, each handled by a different program, which is why a single server can run several services at once.

What are the four things every backend server must do?

Listen for requests on the right port, receive and parse the incoming bytes for their inputs, apply business logic, and send back an appropriate response. Every web framework is an automation of these four steps.

Walk through what happens when you hit https://api.uber.com/api/v1/cars.

DNS resolves api.uber.com to an IP address. Your client opens a TCP connection to that IP on port 443 (implied by https) and completes the TLS handshake. It then sends an HTTP GET for the path /api/v1/cars with the query params as input. The server parses it, runs its logic, and returns a response.

Why 443 for the Uber request, when no port appears in the URL?

The scheme sets a default port: https implies 443 and http implies 80. Because the URL starts with https and states no port, the connection goes to 443 unless one is written explicitly, like :8443.

What do telnet and nc let you do that a browser hides?

They open a raw TCP connection to a host and port with nothing layered on top, so you can check whether anything is listening and even type an HTTP request by hand. nc -l <port> also lets you play the server. They expose the plumbing a browser or framework normally handles for you.

You get "connection refused" on a port. What does that tell you?

The machine is reachable but no process is listening on that specific port, the shop is empty. It is a listener or wrong-port problem, not network latency. Check that the service is running and bound to the port you expect.

Why can you type an HTTP request by hand at all?

HTTP is a plain-text protocol carried over a TCP connection. A minimal request is just a request line, method, path, version, followed by a blank line to end the headers. Because it is text, any tool that opens a TCP connection can send a valid request.

What does curl do that telnet does not?

curl automates the entire exchange: DNS resolution, opening the connection, building a well-formed HTTP request, and printing the response. telnet only gives you a raw pipe; you must speak HTTP yourself. curl is the convenient shortcut for the same conversation.

Are query parameters a safe place for any kind of input?

No. Query params sit in the URL, so they get logged by servers and proxies and can be cached or shared. They are fine for filters and search terms but wrong for passwords, tokens, or large payloads, which belong in a request body over a POST.


2.9Key takeaways#

  • A backend is a loop: listen, parse, process, respond. Frameworks automate it; they don't replace it.
  • IP finds the machine, port finds the service. One IP, many ports, many services.
  • A request starts with DNS resolution, then a TCP connection, then the HTTP text. HTTP rides on TCP.
  • Ports are 16-bit numbers (0–65535); 80 = HTTP, 443 = HTTPS, dev servers on 8080/8081.
  • HTTP is text. You can type a request by hand with telnet/nc, or let curl do it in one line.
  • "Connection refused" means nothing is listening on that port, not that the network is slow.
listen · parse · process · respond IP = machine port = service DNS resolution TCP connection HTTP over TCP :80 http · :443 https nc -l <port> telnet host port curl query params = input connection refused

Microexercises — Build the Muscle#

This lesson is about the layer underneath the framework, so the practice is deliberately hands-on-the-wire. Do each before revealing the walkthrough — parse the URL on paper, type the raw request into a real terminal. Feeling the bytes once is what makes the framework's convenience make sense.

EX 1Dissect a request URL#

A mobile app fires the request below. Without running anything, split it into its parts and say which of the backend's four jobs (listen · receive&parse · process · respond) each part feeds.

the URL
https://api.qeats.com:8081/restaurants/search?lat=28.6&lng=77.2&cuisine=biryani
Show the full walkthrough

Read it left to right; every component answers a different question.

PartValueWhat it decides
schemehttpsTransport + TLS, and the default port (443) if none is written
hostapi.qeats.comWhich machine — DNS resolves it to an IP (the building)
port8081Which service on that machine (the shop) — overrides the https default of 443
path/restaurants/searchWhich endpoint / handler on the server
querylat=28.6, lng=77.2, cuisine=biryaniThe inputs to that handler

Now map those onto the four jobs:

  • Listen — the server must already be bound to port 8081 on that host, or the connection is refused before anything else can happen.
  • Receive & parse — it reads the path to pick the handler, and parses the three query params into typed inputs (two doubles and a string).
  • Process — the search logic runs with lat/lng/cuisine.
  • Respond — it writes back the matching restaurants.
the port subtlety

The port here is :8081, not the https default of 443. Written explicitly, it wins. Drop the :8081 and the very same URL would hit 443. That's the address-vs-port split: api.qeats.com gets you to the building; :8081 gets you to the specific shop inside it.

EX 2Be the client with raw HTTP — then read two failures#

With a server you can reach on localhost:8080 (the Hello World app from the next session works perfectly), open a raw TCP connection and type an HTTP request by hand — no browser, no curl. Then interpret two error outcomes.

part A — open a raw pipe to the port
nc localhost 8080

...then type exactly this. The blank line after the headers is required — it's what tells the server the request is finished:

type this, then press Enter twice
GET /helloworld?name=Neo HTTP/1.1
Host: localhost
Connection: close
Show the full walkthrough

What a healthy reply looks like — a status line, headers, a blank line, then the body:

the server's response
HTTP/1.1 200 OK
Content-Type: text/plain;charset=UTF-8
Content-Length: 21

Hello World, I am Neo!

What you just proved: HTTP is nothing but text sent over a TCP connection. You performed, by hand, the request half of the listen → parse → process → respond loop; the server did the other three. The mandatory blank line is the protocol's "end of headers" marker — omit it and the server keeps waiting for more, so nothing ever comes back.

Now read two failures:

  • Connection refused. nc: connect to localhost port 8080 (tcp) failed: Connection refused — nothing is listening on 8080. The server isn't running, or it's on a different port. "Refused" is the OS actively saying no one is home at that shop. Fix: start the app, or point at the right port.
  • Opens, then hangs. The connection is accepted but after you send the request you get nothing. Something is listening, but you didn't send a complete request — almost always the missing terminating blank line, so the server is still waiting for headers. Fix: send the empty line (press Enter again after the last header).
the shortcut — once you've felt the raw version
curl writes that same request for you
curl "http://localhost:8080/helloworld?name=Neo"

curl composes the identical request text, adds the blank line, and prints the body — but it's the exact same conversation you just had by hand.

scheme · host · port · path · query https → :443 default explicit port wins listen · parse · process · respond nc / telnet blank line ends headers connection refused = nothing listening curl = the shortcut