Обращение к внешнему REST API из кода
Как ранее и говорилось, REST API служит по большей части как способ коммуникации между двумя программами. В этом уроке мы подробнее обсудим как отправлять запросы не с помощью внешнего клиента на компьютере, а прямо из программного кода.
В любом языке программирования можно найти собственные HTTP клиенты, которые позволяют взаимодействовать с сетевыми ресурсами средствами HTTP протокола. В Ruby для данных целей существует встроенный пакет Net::HTTP
. Он поставляется в стандартной библиотеке вместе с самим языком (точно так же как и open-uri
или csv
). Помимо встроенного клиента существуют еще и отдельные библиотеки, такие как faraday
или http.rb
и другие, но в рамках данного данного урока мы подробнее остановимся на Net::HTTP
, так как он:
Встроенный в стандартную поставку языка
Основная масса клиентов основаны на его функциях, просто предоставляя чуть более удобный API для разработчика по использованию.
Для того, чтобы начать использовать клиент, необходимо добавить зависимость в .rb
файл в виде require 'net/http'
. Помимо этого, клиент дял работы с URL адресом ресурса требует использование встроенной библиотеки uri
.
Посмотрим на пример использования данной библиотеки при обращении Dad Jokes API:
# зависимость HTTP клиента
require 'net/http'
# зависимость утилиты для работы с URL
require 'uri'
# Базовый адрес без каких либо параметров запроса в виде объекта URI
base_url = URI.parse('https://api.chucknorris.io/jokes/random')
# сохраняем наши параметры в виде хэш таблицы для удобства
query_params = {
'category': 'dev'
}
# Строим URI объект из базового адреса
# Также превращаем нашу карту параметров в строку формата ?key=value
# Поулчаем в итоге https://api.chucknorris.io/jokes/random?category=dev
request_url = URI.join(base_url, "?#{URI.encode_www_form(query_params)}")
# Собираем GET запрос с адресом, указанным в URI
# Помимо GET запроса, в пакете `Net::HTTP` можно будет найти POST, DELETE и тд
request = Net::HTTP::Get.new(request_url)
# Добавление заголовка (Header) с ключом Accept и значением text/plain
# В зависимости от значения сервер может возвращать ответ в различных текстовых форматах
# text/plain - простая строка, application/json - в формате JSON, text/html - ответ будет в виде HTML страницы
request['Accept'] = 'text/plain'
# Создание объекта, который служит для отправки и получения ответов
http = Net::HTTP.new(request_url.host, request_url.port)
http.use_ssl = true # Параметр необходимый при работе с протоколом HTTPS
# С помощью HTTP клиента отправляем собранный нами HTTP запрос
response = http.request(request)
puts "code: #{response.code}, body: #{response.body}"
В данном примере мы получили классическую шутку от Чака Нориса в формате обычной строки.
Давайте попробуем поработать с API в формате JSON изменив заголовок request['Accept'] = 'application/json'
В ответ мы получим строку в формате JSON. Но с таким форматом тяжело работать, поэтому давайте превратим нашу строку в JSON объект
require 'net/http'
require 'uri'
require 'json'
base_url = URI.parse('https://api.chucknorris.io/jokes/random')
query_params = {
'category': 'dev'
}
request_url = URI.join(base_url, "?#{URI.encode_www_form(query_params)}")
request = Net::HTTP::Get.new(request_url)
request['Accept'] = 'application/json'
http = Net::HTTP.new(request_url.host, request_url.port)
http.use_ssl = true
response = http.request(request)
json_response = JSON.parse(response.body)
puts "code: #{response.code}"
puts "created at #{json_response['created_at']}"
puts "joke: #{json_response['value']}"
Задание weather_info
Внимание! это задание необходимо разместить в директории модуля 11_network/weather_info
Напишите приложение, которые будет спрашивать в консоли страну и город пользователя, а в ответ возвращать текущую дату и время, температуру в цельсиях на данный момент времени, а также количество осадков в виде дождя в мм.
Пример:
> Из какой вы страны ?
< Russia
> Из какого вы города ?
< Moscow
> 2023-03-24 12:41:15 3 градуса, 10 мм осадков
Рекоммендации:
Так как open-meteo для определния погоды ожидает получить координаты, то для начала зная город и страну вам необходимо опредеть координаты этого населенного пункта с помощью geocoding API
Хорошая практика создавать отдельные классы-клиенты для каждого ресурса к которому собираетесь образаться. Создайте классы
MeteoClient
иGeocodingClient
в которых у вас будет содержаться логика для взаимодействия с тем или иным API
Дополнительный материал
Last updated