# Io / Github / Biezhi / Java11 / Http

## Overview

This module appears to be a small collection of Java 11 `HttpClient` examples. It demonstrates how to perform synchronous and asynchronous requests, send JSON payloads, download and upload files, configure a proxy, add basic authentication, and force HTTP/2 behavior. In other words, it exists as a reference module for learning the Java 11 HTTP client API rather than as a reusable service layer.

The code is centered around a single example class, [`Example`](src/main/java/io/github/biezhi/java11/http/Example.java:26), plus a minimal data holder, [`Foo`](src/main/java/io/github/biezhi/java11/http/Foo.java:7), used for JSON serialization in the POST example.

## Key Classes and Interfaces

### [`Example`](src/main/java/io/github/biezhi/java11/http/Example.java:26)

`Example` is the main entry point for the module. It groups together a set of static demonstration methods, each focused on one HTTP client capability. The class is intentionally procedural: each method creates its own `HttpClient`, builds a request, executes it, and prints the result to standard output.

#### `syncGet(String uri)`
- Builds a default `HttpClient` with `HttpClient.newHttpClient()`.
- Creates a GET request from the provided `uri` string.
- Sends the request synchronously with `client.send(...)` and a string body handler.
- Prints the response status code and response body.
- Throws `Exception`, so callers do not need to handle request construction or I/O details inside this method.

This is the simplest example in the module and shows the blocking request style.

#### `asyncGet(String uri)`
- Builds a default client and GET request like `syncGet`.
- Uses `client.sendAsync(...)` to return a `CompletableFuture<HttpResponse<String>>`.
- Registers a `whenComplete(...)` callback that prints either the exception stack trace or the response body and status code.
- Calls `.join()` to wait for completion.

This method demonstrates the non-blocking API shape, but it still blocks at the end via `join()`, making it more of a completion-waiting example than a fully asynchronous pipeline.

#### `asyncPost()`
- Creates a `Foo` instance and assigns sample values to its fields.
- Serializes `Foo` to JSON using `Gson`.
- Builds a POST request to `https://httpbin.org/post` with `Content-Type: application/json`.
- Sends the request asynchronously and prints the response body and status code.

This method is the only place in the module that depends on `Foo`. It shows how Java 11 HTTP requests can be combined with a JSON library for payload construction.

#### `downloadFile()`
- Creates a temporary file with `Files.createTempFile(...)`.
- Sends a GET request to `https://labs.consol.de/`.
- Uses `HttpResponse.BodyHandlers.ofFile(tempFile)` so the response body is written directly to disk.
- Prints the response status and the resulting file path.

This example demonstrates file-backed response handling rather than loading the response into memory.

#### `uploadFile()`
- Builds a POST request to `http://localhost:8080/upload/`.
- Uses `HttpRequest.BodyPublishers.ofFile(Paths.get("/tmp/files-to-upload.txt"))` to stream file contents as the request body.
- Consumes the response with `BodyHandlers.discarding()` because only the status code is printed.

This method shows the upload side of the HTTP client API and assumes a local upload endpoint exists.

#### `proxy()`
- Creates a client with `HttpClient.newBuilder()`.
- Sets a proxy using `ProxySelector.of(new InetSocketAddress("127.0.0.1", 1080))`.
- Sends a GET request to `https://www.google.com`.
- Prints the status code and body.

This is the module’s proxy configuration example and demonstrates how proxy settings are attached when the client is built, not per request.

#### `basicAuth()`
- Creates an `HttpClient` with a custom `Authenticator`.
- Supplies a hard-coded `PasswordAuthentication` with username `username` and password `password`.
- Sends a GET request to `https://labs.consol.de`.
- Prints the response.

This method illustrates Java’s built-in authentication hook. The credentials are placeholders and should be replaced before use in a real environment.

#### `http2()`
- Builds a client with redirect handling enabled via `HttpClient.Redirect.NORMAL`.
- Forces HTTP/2 with `HttpClient.Version.HTTP_2`.
- Sends a GET request asynchronously to `https://http2.akamai.com/demo`.
- Prints the response body and status code when complete.

This is the module’s HTTP/2 demonstration and shows how transport options are configured at client construction time.

#### `getURIs(List<URI> uris)`
- Accepts a list of `URI` values.
- Converts each URI into a `HttpRequest` using a stream pipeline.
- Fires all requests with `client.sendAsync(...)`.
- Uses `CompletableFuture.allOf(...)` to wait for all requests to finish.

This method is the module’s parallel-request example. It does not aggregate or print the responses; it only waits for completion.

#### `main(String[] args)`
- Serves as a manual demo launcher.
- Currently calls `asyncPost()` and leaves the other examples commented out.

Because the module is a demo collection, `main` acts as a convenient scratchpad for trying out one scenario at a time.

### [`Foo`](src/main/java/io/github/biezhi/java11/http/Foo.java:7)

`Foo` is a minimal data carrier used by the POST example. It contains two package-private fields:

- `String name`
- `String url`

The class has no methods, constructors, or behavior. Its only role is to provide a simple object that `Gson` can convert into JSON before the request body is sent.

## How It Works

The module follows a consistent pattern:

1. Create an `HttpClient`.
2. Build a `HttpRequest` for a specific target.
3. Choose the appropriate request body publisher or response body handler.
4. Execute the request synchronously or asynchronously.
5. Print the result.

That pattern is repeated across the examples to isolate the API feature being demonstrated.

### Typical GET flow

For `syncGet` and `asyncGet`, the flow is straightforward:

- Convert a string into a `URI`.
- Build a request with `.uri(...)` and `.build()`.
- Execute the request with either `send(...)` or `sendAsync(...)`.
- Handle the response as a `String`.

The synchronous variant returns only after the server responds. The asynchronous variant registers a completion callback and then waits with `join()`.

### JSON POST flow

`asyncPost()` adds one more step before sending:

- Build a `Foo` object.
- Serialize it with `Gson`.
- Wrap the JSON text in `BodyPublishers.ofString(...)`.
- Send it with `Content-Type: application/json`.

This is the clearest example of how the module combines HTTP client code with a payload model.

### File transfer flow

The module demonstrates both sides of file transfer:

- `downloadFile()` writes a response body directly to a temporary file.
- `uploadFile()` streams a local file into the request body.

These methods show that Java 11 `HttpClient` can integrate with `java.nio.file` without manual buffering.

### Concurrent request flow

`getURIs(List<URI>)` maps each URI to an independent request, starts them all with `sendAsync`, and then coordinates completion with `CompletableFuture.allOf(...)`. The method is useful as an example of fan-out/fan-in request handling, although it does not inspect the returned responses.

## Data Model

The module does not define a rich domain model. The only explicit data class is [`Foo`](src/main/java/io/github/biezhi/java11/http/Foo.java:7), which appears to be a simple serialization target for outbound JSON.

### `Foo`
- `name`: string value sent in the JSON body.
- `url`: string value sent in the JSON body.

There are no getters, setters, validation rules, or annotations. That means the class depends entirely on Gson’s default field serialization behavior.

## Dependencies and Integration

This module connects to several standard Java APIs and one external JSON library:

- `java.net.http.HttpClient`, `HttpRequest`, and `HttpResponse` for HTTP communication.
- `java.net.URI`, `ProxySelector`, `Authenticator`, and `PasswordAuthentication` for request configuration.
- `java.nio.file.Files`, `Path`, and `Paths` for file-backed upload and download examples.
- `java.util.concurrent.CompletableFuture` for asynchronous coordination.
- `com.google.gson.Gson` for JSON serialization in the POST example.

The code also depends on external endpoints for demonstration purposes, including `httpbin.org`, `labs.consol.de`, `http2.akamai.com`, and a local server at `localhost:8080`.

## Mermaid Overview

```mermaid
flowchart TD
    ExampleClass["Example"]
    FooClass["Foo"]
    HttpClientClass["java.net.http.HttpClient"]
    HttpRequestClass["java.net.http.HttpRequest"]
    HttpResponseClass["java.net.http.HttpResponse"]
    GsonClass["com.google.gson.Gson"]
    FileSystemClass["java.nio.file.Files and Path"]
    ProxyClass["ProxySelector and Authenticator"]
    ExampleClass --> HttpClientClass
    ExampleClass --> HttpRequestClass
    ExampleClass --> HttpResponseClass
    ExampleClass --> GsonClass
    ExampleClass --> FileSystemClass
    ExampleClass --> ProxyClass
    ExampleClass --> FooClass
```

## Notes for Developers

- The module is example-oriented, not production-oriented. Most methods print directly to stdout instead of returning values.
- Several methods rely on reachable external services. If one of those services is unavailable, the example will fail even if the code is correct.
- `basicAuth()` uses placeholder credentials and should not be treated as a secure credential storage pattern.
- `uploadFile()` assumes `/tmp/files-to-upload.txt` exists. The method will fail if that file is missing.
- `getURIs(List<URI>)` currently discards the response content. If you need to inspect results, this method is the most obvious extension point.
- The client is configured per example rather than shared globally. That keeps the snippets isolated, but it also means there is no central place for common settings.
- `Foo` has package-private fields, which is convenient for Gson but less encapsulated than typical application DTOs.
