Обращение к внешнему 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