본문 바로가기
개발 (ENG)

Understanding the Real Nature of HTTP Requests: A Look Beneath High-Level Clients

by 새싹 아빠 2025. 12. 9.

The HTTP clients we commonly use—such as RestTemplate, fetch, and axios—let us send requests with very simple, high-level calls. Because of this convenience, we rarely get to see what actually happens underneath. By looking at a lower-level API like HttpURLConnection, we can clearly understand how an HTTP request is constructed and transmitted.

 

1. Example of a Low-Level HTTP Request

Below is a simple example that sends JSON data with a POST request and reads the response as a string.


public static String sendJsonPost(String targetUrl, String jsonBody) throws IOException {
    URL url = new URL(targetUrl);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();

    conn.setRequestMethod("POST");
    conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
    conn.setRequestProperty("Accept", "application/json");
    conn.setDoOutput(true);

    try (OutputStream out = conn.getOutputStream()) {
        byte[] data = jsonBody.getBytes(StandardCharsets.UTF_8);
        out.write(data);
    }

    StringBuilder responseText = new StringBuilder();
    try (BufferedReader reader =
                 new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {

        String line;
        while ((line = reader.readLine()) != null) {
            responseText.append(line);
        }
    }

    return responseText.toString();
}

A single line of code in a tool like RestTemplate internally performs the same sequence of steps. Seeing a manual implementation like this makes it easier to understand how HTTP communication actually works.

 

2. Why Strings (JSON) Must Be Converted to Bytes

Although HTTP often appears text-based, every request and response is ultimately transmitted as a byte stream. A string cannot be written directly to the network; it must first be converted into a byte array.


byte[] data = jsonBody.getBytes(StandardCharsets.UTF_8);
out.write(data);

This process essentially means:

  • Convert the JSON string into a UTF-8 encoded byte array.
  • Write that byte array into the HTTP request body.

High-level libraries like fetch and RestTemplate handle this automatically, so we rarely think about this conversion explicitly.

 

3. Reading the Response Is Also Byte-Based


BufferedReader reader =
    new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));

The server's response also arrives over the network as a stream of bytes. It must be decoded back into characters using the appropriate charset—UTF-8 in this example—before being assembled into a string.

 

4. Why We Hardly Ever See Code Like This

Most modern development environments already provide high-level HTTP clients.

  • Browser: fetch, axios
  • Spring: RestTemplate, WebClient
  • Android/Java: OkHttp

These tools manage the entire process—stream creation, byte conversion, error handling, and encoding—so developers rarely encounter the lower-level details. Because of this abstraction, the actual structure of an HTTP request often remains hidden.

 

Summary

  • HTTP communication is fundamentally the exchange of byte streams.
  • High-level libraries conceal this fact by providing very simple interfaces.
  • Examining low-level APIs reveals how requests and responses actually work beneath the surface.

Understanding these lower-level mechanisms can be helpful not only for learning, but also for diagnosing unexpected network issues that might occur in real environments.