3.1 BodyPublishers

Я надеюсь, вы не забыли, что кроме GET-запросов, есть еще PUT и POST-запросы, когда к запросу нужно еще добавить request body, то есть тело запроса.

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

И начнем мы с самой простой – отсутствие тела запроса. Да, бывает и так.


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

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

3.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.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();

3.4 ofByteArray()

Еще один распространенный сценарий – отправить на сервер набор байт. Например, ты сериализовал некий объект в виде набора байт, что-то зашифровал, или просто хочешь переслать некий буфер данных. Для этого понадобится метод .ofByteArray().

В качестве параметра этот метод принимает массив байт. Пример:


byte[] data = "Мое секретное сообщение".getBytes();
byte[] dataEncripted = SuperEncriptor.encript(data);
 
HttpRequest request = HttpRequest.newBuilder()
   .uri(new URI("https://javarush.com"))
   .headers("Content-Type", "application/octet-stream")
   .POST(HttpRequest.BodyPublishers.ofByteArray(dataEncripted))
   .build();

3.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(). Но если хочешь послать данные асинхронно или нужно реализовать какой-то особо сложный сценарий, то можешь воспользоваться этим методом.