JavaRush /Курсы /JSP & Servlets /Добавление body в HttpRequest

Добавление body в HttpRequest

JSP & Servlets
10 уровень , 2 лекция
Открыта

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

Комментарии (14)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Максим Уровень 115
10 сентября 2025
Не хватает практических задачек
Олег Уровень 111 Expert
28 июля 2023
Могу ошибаться, но компилятор ругается на точку с запятой в этой строчке кода: .POST(HttpRequest.BodyPublishers.ofInputStream (() -> is;))
Anonymous #3268884 Уровень 24
13 августа 2023
ага, вот и я думаю, зачем там точка с запятой
Дмитрий Уровень 108 Expert
15 июня 2023
Пункт 3.5, второй абзац, пропущена буква Т Для этого есть специальная функция – ofInputStream(). И она очень хитрая. Она позволяет организовать пересылку данных из потока в поток, прикрепить к POS-запросу поток данных, который еще даже не открыт
jvatechs Уровень 111 Expert
13 июня 2023
Хорошо было бы также создать какой-нибудь демо-сервер от Javarush, куда можно было бы отправлять простенькие GET, POST, PUT, DELETE запросы.
Юрий Кохно Уровень 62 Expert
7 июля 2023
Замечательная идея!
jvatechs Уровень 111 Expert
9 июля 2023
попробуй следующий фри-сервис: https://jsonplaceholder.typicode.com/ в свое время здорово помог.
Anonymous #3268884 Уровень 24
13 августа 2023
супер! А то я, будучи чайником, уже начал обдумывать решение проблемы в чайник-стиле: установить линукс, настроить сервер на своем компе и общаться сам с собой через локалхост
Павел Уровень 75 Expert
31 мая 2024
Работает только с vpn
jvatechs Уровень 111 Expert
13 июня 2023
может не:

byte[] dataEncripted = SuperEncriptor.encript(data);
а:

byte[] dataEncrypted = SuperEncryptor.encrypt(data);
и потом, в предыдущей лекции вы предлагаете юзать в основном URI.create вместо new URI дабы избежать выброса исключения, а тут вовсю new URI. Логика?
JavaCoder Уровень 51
10 января 2023
Может не fromFile(), а ofFile() ?
Евгений Уровень 90
14 октября 2022
В п.3.2 можно передать не просто строку, а строку в виде JSON объекта. Как раз такой вариант и применяется на практике.
Сергей Ильин Уровень 35
23 января 2023
HttpRequest request = HttpRequest.newBuilder() .uri(new URI("https://javarush.com")) .POST(HttpRequest.BodyPublishers.ofString("Привет", Charset. US-ASCII))) .build(); а как получить ответ если пост возвращает строку
jvatechs Уровень 111 Expert
14 июня 2023
за ответ видимо отвечает объект HttpResponse, будет что-то типа этого:

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.statusCode());
        System.out.println(response.body());