HttpRequest.newBuilder: примеры (JAVA)

Построитель HTTP-запросов в Java
Раздел: Работа с HTTP (HTTP Client, URLConnection)
HttpRequest.newBuilder(URI uri): HttpRequest.Builder

Описание

Метод HttpRequest.newBuilder принадлежит пакету java.net.http и служит для создания экземпляра HttpRequest.Builder. Этот билдер используется для поэтапной настройки HTTP-запроса, включая указание URI, заголовков, тела, версии протокола и таймаута. API появился вместе с Java HTTP Client, доступным с Java 11.

Доступные варианты вызова:

  • static HttpRequest.Builder newBuilder() - возвращает новый пустой билдер без установленного URI.
  • static HttpRequest.Builder newBuilder(URI uri) - возвращает новый билдер с установленным URI (удобный вариант для компактного кода).

Основные методы HttpRequest.Builder (кратко):

  • uri(URI uri) - устанавливает целевой URI.
  • version(HttpClient.Version version) - выбирает версию протокола (HTTP_1_1 или HTTP_2).
  • header(String name, String value) - добавляет заголовок (не заменяет существующие).
  • setHeader(String name, String value) - устанавливает заголовок, заменяя предыдущие значения.
  • headers(String... headers) - добавляет несколько заголовков в виде пар имя, значение.
  • timeout(Duration duration) - устанавливает таймаут выполнения запроса по времени.
  • expectContinue(boolean) - включает механизм Expect: 100-continue.
  • GET(), POST(HttpRequest.BodyPublisher), PUT(HttpRequest.BodyPublisher), DELETE() - стандартные методы для выбора HTTP-метода и тела.
  • method(String method, HttpRequest.BodyPublisher bodyPublisher) - явная установка произвольного метода с телом (или HttpRequest.BodyPublishers.noBody() для пустого тела).
  • build() - собирает и возвращает объект HttpRequest. Перед вызовом build() должен быть установлен URI, иначе будет исключение.

Возвращаемое значение: HttpRequest.newBuilder возвращает объект типа HttpRequest.Builder. Методы билда возвращают тот же билдер для цепочек вызовов. Метод build() возвращает готовый HttpRequest, пригодный для передачи в HttpClient.send или sendAsync.

Особенности

  • Билдер потокобезопасным не является; его использование предполагает локальную конфигурацию в одном потоке.
  • Некоторые методы клиента (HttpClient) влияют на поведение выполненного запроса, например, поддержка HTTP/2 и TLS.

Короткие примеры

1. Простой GET

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://httpbin.org/get"))
    .GET()
    .build();

HttpResponse resp = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.statusCode());
System.out.println(resp.body().substring(0, 200));
200
{"args":{},"headers":{...},"url":"https://httpbin.org/get"...}

2. POST с телом и заголовками

HttpRequest request = HttpRequest.newBuilder(URI.create("https://httpbin.org/post"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("{\"name\":\"Alice\"}"))
    .build();

HttpResponse resp = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.statusCode());
System.out.println(resp.body());
200
{"json":{"name":"Alice"},"headers":{...}}

3. Указание версии HTTP и таймаута

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://httpbin.org/anything"))
    .version(HttpClient.Version.HTTP_2)
    .timeout(java.time.Duration.ofSeconds(5))
    .GET()
    .build();

HttpResponse resp = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.version());
System.out.println(resp.statusCode());
HTTP_2
200

4. Отправка файла как тело

HttpRequest request = HttpRequest.newBuilder(URI.create("https://httpbin.org/post"))
    .header("Content-Type", "application/octet-stream")
    .POST(HttpRequest.BodyPublishers.ofFile(java.nio.file.Path.of("./data.bin")))
    .build();

HttpResponse resp = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.statusCode());
200

Похожие инструменты в Java

В экосистеме Java имеются альтернативы для выполнения HTTP-запросов:

  • HttpURLConnection
  • Классическая реализация из JDK до Java 11. Подходит для простых задач, но требует больше кода, вручную управляет потоками и заголовками.

  • Apache HttpClient
  • Более мощная и настраиваемая библиотека с богатым набором опций, поддержкой пула соединений и расширенной обработкой ошибок. Предпочтительнее для сложных корпоративных сценариев.

  • OkHttp
  • Быстрая и удобная библиотека от Square, часто используется в Android и микро-сервисах. Удобнее в асинхронных и многопоточных сценариях.

Выбор зависит от требований: для современных приложений без внешних зависимостей java.net.http предпочтительнее; при необходимости расширенных возможностей можно рассмотреть сторонние клиенты.

Аналоги в других языках

Ниже приведены краткие примеры создания аналогичных HTTP-запросов в популярных языках и отличия подходов.

PHP (cURL)

$ch = curl_init('https://httpbin.org/post');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['name' => 'Alice']));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resp = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $code; echo "\n"; echo substr($resp, 0, 200);
200
{"json":{"name":"Alice"},...}

JavaScript (fetch, браузер / node-fetch)

fetch('https://httpbin.org/post', {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({name: 'Alice'})
}).then(r => r.json()).then(console.log);
{ json: { name: 'Alice' }, ... }

Python (requests)

import requests
r = requests.post('https://httpbin.org/post', json={'name':'Alice'})
print(r.status_code)
print(r.json())
200
{'json': {'name': 'Alice'}, ...}

C# (HttpClient)

using System.Net.Http;
using System.Text;

var client = new HttpClient();
var resp = await client.PostAsync("https://httpbin.org/post",
    new StringContent("{\"name\":\"Alice\"}", Encoding.UTF8, "application/json"));
Console.WriteLine((int)resp.StatusCode);
Console.WriteLine(await resp.Content.ReadAsStringAsync());
200
{ "json": { "name": "Alice" }, ... }

Go (net/http)

resp, _ := http.Post("https://httpbin.org/post", "application/json", 
    bytes.NewBufferString(`{"name":"Alice"}`))
body, _ := io.ReadAll(resp.Body)
fmt.Println(resp.StatusCode)
fmt.Println(string(body)[:200])
200
{ "json": { "name": "Alice" }, ... }

Kotlin (kotlinx.coroutines + java.net.http)

val client = HttpClient.newHttpClient()
val request = HttpRequest.newBuilder(URI.create("https://httpbin.org/get")).GET().build()
val resp = client.send(request, HttpResponse.BodyHandlers.ofString())
println(resp.statusCode())
println(resp.body())
200
{...}

Lua (socket.http)

local http = require('socket.http')
local body, code = http.request('https://httpbin.org/get')
print(code)
print(string.sub(body,1,200))
200
{...}

Отличия: в Java используется типизированный билдер и BodyPublisher. Во многих скриптовых языках интерфейс более динамичен и компактен. В C# и Kotlin подходы близки к Java. В Go и C# нативные библиотеки дают контроль над соединениями аналогично Apache/OkHttp.

Типичные ошибки

1. Отсутствие URI перед build()

HttpRequest request = HttpRequest.newBuilder().GET().build();
Exception in thread "main" java.lang.IllegalStateException: request URI must be set

2. Передача null в методы

HttpRequest.newBuilder().uri(null);
Exception in thread "main" java.lang.NullPointerException

3. Некорректное использование тела с GET

Стандартные вызовы должны использовать GET() без тела. При попытке указать метод явно с телом для GET поведение зависит от сервера, но чаще возникает логическая ошибка.

// Плохая практика: метод GET с телом
HttpRequest.newBuilder()
  .uri(URI.create("https://example.com"))
  .method("GET", HttpRequest.BodyPublishers.ofString("data"))
  .build();
Возможны неожиданные ответы сервера или отклонение запроса

4. Неправильное указание заголовков

request = HttpRequest.newBuilder()
    .uri(URI.create("https://httpbin.org/post"))
    .headers("Content-Type") // не пара имя, значение
    .POST(HttpRequest.BodyPublishers.ofString("x"))
    .build();
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException

5. Неправильный BodyPublisher

HttpRequest.newBuilder()
    .uri(URI.create("https://example.com"))
    .POST(null)
    .build();
Exception in thread "main" java.lang.NullPointerException

Рекомендуется проверять входные данные, устанавливать URI и использовать подходящие BodyPublishers из HttpRequest.BodyPublishers.

Изменения в последних версиях

Интерфейс java.net.http был введен в Java 11. С тех пор API стабилен, но происходили улучшения в сопутствующих возможностях:

  • Поддержка HTTP/2 и улучшенное управление соединениями через HttpClient.
  • Добавлены удобные фабрики для BodyPublishers и BodyHandlers (например, потоковые и файловые публикашеры).
  • Мелкие дополнения в виде перегрузки newBuilder(URI) и дополнительных удобств для асинхронной обработки.

Сам HttpRequest.newBuilder изменений не испытывал радикальных: он по-прежнему возвращает HttpRequest.Builder и служит точкой конфигурации для запроса.

Расширенные примеры

1. Отправка multipart/формы (сборка тела вручную)

Пример java
// Пример упрощен: вручную формируется multipart тело
String boundary = "----Boundary" + System.currentTimeMillis();
String body = "--" + boundary + "\r\n" +
    "Content-Disposition: form-data; name=\"file\"; filename=\"data.txt\"\r\n" +
    "Content-Type: text/plain\r\n\r\n" +
    "Hello\r\n" +
    "--" + boundary + "--\r\n";

HttpRequest req = HttpRequest.newBuilder(URI.create("https://httpbin.org/post"))
    .header("Content-Type", "multipart/form-data; boundary=" + boundary)
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse r = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(r.statusCode());
200

2. Потоковая отправка больших данных (ofInputStream)

Пример java
Path file = Path.of("large.bin");
HttpRequest req = HttpRequest.newBuilder(URI.create("https://example.com/upload"))
    .header("Content-Type", "application/octet-stream")
    .POST(HttpRequest.BodyPublishers.ofInputStream(() -> Files.newInputStream(file)))
    .build();

HttpResponse resp = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.statusCode());
201

3. Асинхронная отправка и отмена

Пример java
HttpClient client = HttpClient.newHttpClient();
HttpRequest req = HttpRequest.newBuilder(URI.create("https://httpbin.org/delay/3"))
    .GET().build();

var future = client.sendAsync(req, HttpResponse.BodyHandlers.ofString());
// Через 1 секунду принимается решение отменить
Thread.sleep(1000);
future.cancel(true);
try {
  var r = future.join();
  System.out.println(r.statusCode());
} catch (Exception e) {
  System.out.println("Запрос отменен: " + e.getClass().getSimpleName());
}
Запрос отменен: CompletionException

4. Использование BodyPublishers.fromPublisher для кастомного стриминга

Пример java
import java.nio.ByteBuffer;
import java.util.concurrent.Flow;

Flow.Publisher publisher = subscriber -> {
  subscriber.onSubscribe(new Flow.Subscription() {
    boolean done = false;
    public void request(long n) {
      if (!done) {
        subscriber.onNext(ByteBuffer.wrap("chunk1\n".getBytes()));
        subscriber.onNext(ByteBuffer.wrap("chunk2\n".getBytes()));
        subscriber.onComplete();
        done = true;
      }
    }
    public void cancel() {}
  });
};

HttpRequest req = HttpRequest.newBuilder(URI.create("https://httpbin.org/post"))
    .POST(HttpRequest.BodyPublishers.fromPublisher(publisher))
    .build();

HttpResponse r = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(r.statusCode());
System.out.println(r.body().substring(0, 200));
200
{... "data": "chunk1\nchunk2\n" ...}

5. Подписание запроса и добавление заголовков аутентификации

Пример java
// Подпись добавляется на уровне заголовка; пример упрощен
String token = "Bearer abcdef123456";
HttpRequest req = HttpRequest.newBuilder(URI.create("https://api.example.com/resource"))
    .header("Authorization", token)
    .GET()
    .build();

var r = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(r.statusCode());
200

Примеры демонстрируют расширенные сценарии: multipart формирование, стриминг больших файлов, кастомные публикашеры и отмена асинхронных задач. В реальных системах стоит уделять внимание обработке исключений и управлению ресурсами (пулы, таймауты, повторные попытки).

джава HttpRequest.newBuilder function comments

En
HttpRequest.newBuilder Creates a new HttpRequest builder