1. BodyPublishers

Я сподіваюся, ти пам'ятаєш, що крім GET-запитів є ще PUT і POST-запити, коли до запиту потрібно ще додати request body – тіло запиту.

Для цього клас HttpRequest має спеціальний внутрішній клас BodyPublisher. Хоча технічно це – інтерфейс, який має кілька реалізацій, про які ми поговоримо нижче

Почнемо з найпростішої – відсутність тіла запиту. Так, може бути й таке.


HttpRequest request = HttpRequest.newBuilder()
   .uri(new URI("https://javarush.com"))
   .POST(HttpRequest.BodyPublishers.noBody())
   .build();

Просто та красиво.

2. ofString()

Другий найпоширеніший варіант – передати якийсь рядок як request body. Робиться це дуже просто:


HttpRequest request = HttpRequest.newBuilder()
   .uri(new URI("https://javarush.com"))
   .headers("Content-Type", "text/plain;charset=UTF-8")
   .POST(HttpRequest.BodyPublishers.ofString("Вітання"))
   .build();

До речі, можна зазначити і кодування рядка, що передається. Це може стати в пригоді, якщо http-сервер, до якого надсилається запит, не працює на UTF8.


HttpRequest request = HttpRequest.newBuilder()
   .uri(new URI("https://javarush.com"))
   .POST(HttpRequest.BodyPublishers.ofString("Вітання", Charset. US-ASCII)))
   .build();

3. ofFile()

Ну і нарешті, ти можеш захотіти додати до POST-запиту файл. Зазвичай саме таким чином твої аватарки заливаються на сервер. Для цього необхідно викликати метод ofFile(), куди передати Path локального файлу:


Path avatar = Path.of("c://avatar.jpeg");
 
HttpRequest request = HttpRequest.newBuilder()
   .uri(new URI("https://javarush.com"))
   .headers("Content-Type", "image/jpeg")
   .POST(HttpRequest.BodyPublishers.ofFile(avatar))
   .build();

4. ofByteArray()

Ще один поширений сценарій – надіслати на сервер набір байт. Наприклад, ти серіалізував якийсь об'єкт у вигляді набору байт, щось зашифрував, або просто хочеш переслати буфер даних. Для цього знадобиться метод .ofByteArray().

Як параметр цей метод приймає масив байт. Приклад:


byte[] data = "Моє секретне повідомлення".getBytes();
byte[] dataEncrypted = SuperEncryptor.encrypt(data);
 
HttpRequest request = HttpRequest.newBuilder()
   .uri(new URI("https://javarush.com"))
   .headers("Content-Type", "application/octet-stream")
   .POST(HttpRequest.BodyPublishers.ofByteArray(dataEncrypted))
   .build();

5. ofInputStream()

Зрештою останній, але не менш цікавий сценарій – це прикріплення InputStream до POST-запиту.

Для цього є спеціальна функція – ofInputStream(). І вона дуже хитра. Вона дозволяє організувати пересилання даних із потоку в потік, прикріпити до POST-запиту потік даних, який ще навіть не відкрито.

До функції ofInputStream() потрібно передати функцію, яка як результат поверне потік InputStream.

Приклад:


byte[] data = "Моє секретне повідомлення".getBytes();
//загортаємо масив байт у потік.
InputStream is = new ByteArrayInputStream(data);
 
HttpRequest request = HttpRequest.newBuilder()
   .uri(new URI("https://javarush.com"))
   .headers("Content-Type", "application/octet-stream")
   .POST(HttpRequest.BodyPublishers.ofInputStream (() -> is;))
   .build();

Думаю, загальний принцип для тебе зрозумілий. Для чого так зробили? Майже завжди ти можеш скористатися методом ofByteArray(). Але якщо хочеш надіслати дані асинхронно або потрібно реалізувати якийсь особливо складний сценарій, можеш скористатися цим методом.