# Io / Github / Biezhi / Java11 / Http

## Overview

This module appears to be a small JDK 11 HTTP client showcase. It demonstrates how to use `java.net.http.HttpClient` for synchronous and asynchronous requests, file transfer, proxy configuration, basic authentication, HTTP/2 access, and simple fan-out requests.

The code is organized as executable examples rather than a reusable library. That makes the module useful as onboarding material for engineers who need a quick reference for Java 11 HTTP client features and the surrounding request-building patterns.

## Key Classes and Interfaces

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

`Example` is the main demonstration class for the package. It groups a set of static methods, each showing one HTTP client capability, and a non-static helper for concurrent request dispatch.

#### Responsibilities

- Build `HttpClient` instances with different capabilities.
- Create `HttpRequest` objects for GET, POST, file upload, and HTTP/2 calls.
- Demonstrate how to consume responses as strings, files, or discarded bodies.
- Show how to wire optional client features such as a proxy and an authenticator.

#### Important methods

- `syncGet(String uri)`
  - Sends a blocking GET request to the provided URI.
  - Takes a single URI string, converts it to a `URI`, and executes `client.send(...)` with `BodyHandlers.ofString()`.
  - Returns `void`, but prints the response status code and body to stdout.

- `asyncGet(String uri)`
  - Sends a GET request asynchronously using `client.sendAsync(...)`.
  - Accepts a URI string and uses `whenComplete(...)` to print either the response or the exception.
  - Calls `.join()` so the example does not exit before the future completes.

- `asyncPost()`
  - Builds a JSON payload from a `Foo` instance using Gson.
  - Sends the payload to `https://httpbin.org/post` with `Content-Type: application/json`.
  - Demonstrates an asynchronous POST flow and prints the response body and status code.

- `downloadFile()`
  - Performs a blocking GET request to `https://labs.consol.de/`.
  - Uses `BodyHandlers.ofFile(tempFile)` to stream the response into a temporary file created with `Files.createTempFile(...)`.
  - Prints the status code and the file path returned by the response body.

- `uploadFile()`
  - Posts the contents of `/tmp/files-to-upload.txt` to `http://localhost:8080/upload/`.
  - Uses `BodyPublishers.ofFile(...)` for the request body and `BodyHandlers.discarding()` for the response.
  - Prints only the status code, which is enough for this example.

- `proxy()`
  - Builds an `HttpClient` with a proxy configured at `127.0.0.1:1080`.
  - Sends a GET request to `https://www.google.com` through that proxy.
  - Demonstrates that proxy routing is configured on the client, not the request.

- `basicAuth()`
  - Builds an `HttpClient` with an `Authenticator` that returns a fixed username and password.
  - Sends a GET request to `https://labs.consol.de`.
  - Shows how the client can participate in HTTP Basic authentication challenges.

- `http2()`
  - Configures the client to prefer HTTP/2 and follow redirects normally.
  - Sends an asynchronous GET request to `https://http2.akamai.com/demo`.
  - Prints the response body and status code after completion.

- `getURIs(List<URI> uris)`
  - Accepts a list of `URI` objects and dispatches requests for them in parallel.
  - Builds a list of `HttpRequest` objects from the URIs, then starts one asynchronous send per request.
  - Uses `CompletableFuture.allOf(...)` to wait for all requests to finish, but does not inspect individual responses.

- `main(String[] args)`
  - Serves as the runnable entry point for the package.
  - The current version has most examples commented out and executes `asyncPost()` by default.
  - This makes the class usable as a quick manual demo runner.

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

`Foo` is a minimal data holder used by `Example.asyncPost()` to create a JSON request body.

#### Responsibilities

- Hold the fields that get serialized into JSON.
- Keep the POST example simple by avoiding an inline map or manual JSON construction.

#### Fields

- `String name`
- `String url`

Both fields are package-private and are populated directly in `Example.asyncPost()` before being serialized with Gson.

## How It Works

### Typical request flow

Most examples follow the same overall pattern:

1. Create an `HttpClient` with either `HttpClient.newHttpClient()` or `HttpClient.newBuilder()`.
2. Build an `HttpRequest` with a target URI and any required headers or body publishers.
3. Send the request synchronously with `send(...)` or asynchronously with `sendAsync(...)`.
4. Handle the response by printing a status code, body, or file location.

### Synchronous vs asynchronous usage

The module contrasts two common styles:

- Synchronous examples such as `syncGet(...)`, `downloadFile()`, `uploadFile()`, `proxy()`, and `basicAuth()` block until the response is available.
- Asynchronous examples such as `asyncGet(...)`, `asyncPost()`, and `http2()` use `CompletableFuture` and `whenComplete(...)` to handle success or failure without blocking the call itself.

In both cases, `.join()` is used in the example code so the JVM waits for completion before exiting.

### Request body handling

The module demonstrates several request body strategies:

- `BodyPublishers.ofString(jsonBody)` for JSON payloads.
- `BodyPublishers.ofFile(Paths.get(...))` for file upload.
- No body for GET requests.

The response side mirrors that flexibility:

- `BodyHandlers.ofString()` for textual responses.
- `BodyHandlers.ofFile(tempFile)` for download-to-disk workflows.
- `BodyHandlers.discarding()` when the response body is irrelevant.

### Parallel fan-out

`getURIs(List<URI>)` shows a lightweight parallel dispatch pattern. It converts each input URI into a request, starts all requests with `sendAsync(...)`, and then waits on a combined `CompletableFuture.allOf(...)`. This appears intended as a simple example of concurrent HTTP calls rather than a fully featured aggregation routine.

## Data Model

There is no rich domain model in this package. The only local data object is [`Foo`](src/main/java/io/github/biezhi/java11/http/Foo.java), which acts as a DTO for the JSON POST example.

- `Foo` contains two string fields: `name` and `url`.
- `Example.asyncPost()` populates those fields and serializes the object with Gson.
- The resulting JSON is sent to `httpbin.org`, which echoes the request for demonstration purposes.

## Dependencies and Integration

### JDK APIs

This module depends primarily on Java 11 standard library APIs:

- `java.net.http.HttpClient`
- `java.net.http.HttpRequest`
- `java.net.http.HttpResponse`
- `java.net.URI`
- `java.net.ProxySelector`
- `java.net.Authenticator`
- `java.nio.file.Files`, `Path`, and `Paths`
- `java.util.concurrent.CompletableFuture`

### External library

- `com.google.gson.Gson` is used only in `asyncPost()` to serialize `Foo` into JSON.

### External services used by the examples

The example methods point at a few concrete endpoints:

- `https://httpbin.org/post`
- `https://labs.consol.de/`
- `http://localhost:8080/upload/`
- `https://www.google.com`
- `https://http2.akamai.com/demo`
- `https://biezhi.me` in commented example calls inside `main(...)`

These are demonstration targets, so they are not a formal dependency of the package, but they matter when running the examples interactively.

## Mermaid Diagram

```mermaid
flowchart TD
    ExampleClass["Example"] --> SyncGet["syncGet(String uri)"]
    ExampleClass --> AsyncGet["asyncGet(String uri)"]
    ExampleClass --> AsyncPost["asyncPost()"]
    ExampleClass --> DownloadFile["downloadFile()"]
    ExampleClass --> UploadFile["uploadFile()"]
    ExampleClass --> Proxy["proxy()"]
    ExampleClass --> BasicAuth["basicAuth()"]
    ExampleClass --> Http2["http2()"]
    ExampleClass --> GetURIs["getURIs(List<URI>)"]
    AsyncPost --> FooClass["Foo"]
```

## Notes for Developers

- This package is written as a tutorial-style sample set. Most methods print results directly instead of returning data, which keeps the examples short but makes them less reusable in application code.
- `asyncGet(...)`, `asyncPost()`, and `http2()` use `.join()` after registering completion handlers. That is convenient for demos, but in production code you would usually avoid blocking at the end unless you explicitly need to wait.
- `uploadFile()` depends on `/tmp/files-to-upload.txt` and `proxy()` depends on a proxy at `127.0.0.1:1080`. Those assumptions are environment-specific and will fail if the local setup differs.
- `basicAuth()` uses placeholder credentials (`username` / `password`). Treat them as example values only.
- `getURIs(List<URI>)` intentionally ignores individual response contents. If you need meaningful aggregation, this method would need to collect and return the responses instead of just waiting for completion.
- `main(String[] args)` currently runs `asyncPost()` by default, so launching the class will make a live network call unless you change the commented lines.
