Хабрахабр

[Из песочницы] Особенности HttpUrlConnection из java.net

Здравствуйте,

сегодня постараюсь рассказать о том, как можно отправить запрос и прочитать ответ от HTTP сервера, используя URLConnection из библиотеки JRE.

Вся наша команда использует Slack для работы и общения. Сейчас изучаем Java в онлайн режиме. Чтобы долго не рассказывать про сам API (это тема для отдельной статьи), скажу коротко: для получения информации о пользователях, нужно было отправить HTTP запрос с URI который обозначает имя метода из API (то есть, обозначает что именно мы хотим получить – в нашем случае нужен был полный список юзеров) и токеном аутентификации slack-приложения. Заинтересовала возможность получения информации о пользователях, используя Slack API. По документации, для получения списка юзеров нужно использовать GET-запрос с URL slack.com/api/users.list, в теле запроса должен быть токен аутентификации в форме application/x-www-form-urlencoded, то есть запрос должен выглядеть примерно так (но есть один нюанс который будет ниже):

GET /users.list HTTP/1.1
Content-Type: application/x-www-form-urlencoded token=xoxp-1234567890-098765-4321-a1b2c3d4e5&limit=100

(где limit=100 это ограничение на максимальное количество юзеров, которое нужно получить)

И, так как я уже сталкивался из HttpUrlConnection, решил попробовать в этот раз.
Для получений сущности URLConnection нужно использовать объект класса java.net. Я знал про библиотеку Apache HttpComponents, но решил попробовать не использовать внешних зависимостей. URL, его конструктор принимает тип String где помимо всего должен быть указан протокол – в нашем случае https.

После получения сущности URL, вызываем метод openConnection() который возвратит нам сущность HttpsUrlConnection.

String url = “https://slack.com/api/users.list”;
URLConnection connection = new URL(url).openConnection();

При этом нужно обработать или пробросить MalformedUrlException и IOException.

По умолчанию будет формироваться GET-запрос, для того чтобы добавить Header используем метод setRequestProperty(), который принимает key и value. После этого переменная connection будет хранить ссылку на объект HttpsUrlConnectionImpl. Ну, и мы это делаем! Нам здесь нужно установить Content-Type который имеет значение application/x-www-form-urlencoded.

connection.setRequestProperty(“Content-Type”, “application/x-www-form-urlencoded”);

Теперь осталось только отправить запрос записав в тело наш токен и лимит. Для этого нужно установить поле doOutput объекта connection в положение true, используя метод setDoOutput();

connection.setDoOutput(true);

Далее самая интересная часть нужно как-то передать наше тело запроса (и весь запрос в OutputStream). Будем использовать OutputStreamWriter:

OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());

Есть один нюанс: после того, как мы вызвали метод getOutputStream() метод запроса меняется на POST, так как GET не предусматривает наличие request body, но благо что slack ни ставит твёрдое ограничение на метод поэтому всё было хорошо. И поэтому GET-запрос должен выглядеть так:

GET /users.list?token=xoxp-1234567890-098765-4321-a1b2c3d4e5&limit=100 HTTP/1.1
Content-Type: application/x-www-form-urlencoded

Но я не стал уже переделывать. И вместо этого наш запрос получился таким:

POST /users.list HTTP/1.1
Content-Type: application/x-www-form-urlencoded token=xoxp-1234567890-098765-4321-a1b2c3d4e5&limit=100

(*некоторые headers ставятся самим HttpsUrlConnection и здесь они отсутствуют)

И так чтоб записать наше тело запроса пользуемся write();.

String reqBody = “token=xoxp-1234567890-098765-4321-a1b2c3d4e5&limit=100”;
writer.write(reqBody);
writer.close();

После этого наш запрос будет отправлен, и мы можем прочитать полученный ответ. Я лично использовал BufferedReader для этой цели.

StringBuilder respBody = new StringBuilder();
BufferedReader reader = new BufferedReader(connection.getInputStream());
reader.lines().forEach(l -> respBody.append(l + “\r\n”);
reader.close();

(*используем lines() чтобы получить Stream на выходе; \r\n – символ CRLF – вставляет переход на новую строку)

После этого, его можно отправлять на следующий этап обработки. И, если мы успешно проходим аутентификацию, переменная respBody должна хранить наш ответ от сервера, что в нашем случае является JSON объектом.

Вот что вышло:

public static String getRawResponseFromSlack() throws MalformedURLException, IOException { String url = "https://slack.com/api/users.list"; String reqBody = "token=xoxp-23476289909-566592298292" + "-682762141574-f0a9feac56d087769519f610b30bd29f" + "&limit=100"; URLConnection connection = new URL(url).openConnection(); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); connection.setDoOutput(true); OutputStreamWriter out = new OutputStreamWriter( connection.getOutputStream()); out.write(reqBody); out.close(); StringBuilder respBody = new StringBuilder(); BufferedReader reader = new BufferedReader( new InputStreamReader(connection.getInputStream())); reader.lines().forEach(l -> respBody.append(l + "\r\n")); reader.close(); return respBody.toString();
}

Надеюсь, было полезно!

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть