REST (REpresentational State Transfer)

31-12-2019

Немного технических деталей

Существует несколько больших классов веб-сервисов для веб-API (мы приведём только 3):

  1. SOAP (Simple Object Access Protocol) - это стандартный протокол, определенный стандартами W3C для отправки и получения запросов и ответов веб-служб.
  2. WSDL (Web Services Description Language) - это язык описания веб-сервисов и доступа к ним, основанный на языке XML.
  3. REST (REpresentational State Transfer) - это основанная на веб-стандартах архитектура, использующая HTTP. В отличие от веб-сервисов на основе SOAP, для веб-API RESTful нет официального стандарта.

REST (REpresentational State Transfer)

REST на сегодняшний день практически вытеснил все остальные подходы, в том числе и подходы, основанные на использовании SOAP и WSDL. Поэтому именно REST API мы и рассмотрим.

Причина его популярности заключается в его простоте, легкости использования, доступе через HTTP и другие. REST – это архитектурный подход, определяющий, как API должны выглядеть.

REST API подразумевает под собой простые правила:

  1. Каждый URL является ресурсом
  2. При обращении к ресурсу методом GET возвращается описание этого ресурса
  3. Метод POST добавляет новый ресурс
  4. Метод PUT изменяет ресурс
  5. Метод DELETE удаляет ресурс

Эти правила предоставляют простой CRUD (Create/Read/Update/Delete) интерфейс для других приложений, взаимодействие с которым происходит через протокол HTTP.

Соответствие CRUD операций и HTTP методов:

CRUD операция HTTP метод Безопасен? Идемпотентен? Описание
CREATE POST нет нет Метод не является ни безопасным, ни идемпотентным. Этот метод наиболее широко используется для создания ресурсов.
READ GET да да Метод является безопасным и идемпотентным. Обычно используется для извлечения информации и не имеет побочных эффектов.
UPDATE PUT нет да Метод является идемпотентным. Вот почему лучше использовать этот метод вместо POST для обновления ресурсов. Избегайте использования POST для обновления ресурсов.
DELETE DELETE нет да Метод используется для удаления ресурсов. Но этот метод не является идемпотентным для всех запросов.
-- OPTIONS да да Метод не используется для каких-либо манипуляций с ресурсами. Но он полезен, когда клиент не знает других методов, поддерживаемых для ресурса, и используя этот метод, клиент может получить различное представление ресурса.
-- HEAD да да Метод используется для запроса ресурса c сервера. Он очень похож на метод GET, но HEAD должен отправлять запрос и получать ответ только в заголовке. Согласно спецификации HTTP, этот метод не должен использовать тело для запроса и ответа.

Термин "безопасный" метод означает, что он предназначен только для получения информации и не должнен изменять состояние сервера. Он не должен иметь побочных эффектов, за исключением безобидных эффектов, таких как: логирование, кеширование, показ баннерной рекламы или увеличение веб-счетчика.

С точки зрения RESTful-сервиса, операция (или вызов сервиса) идемпотентна тогда, когда клиенты могут делать один и тот же вызов неоднократно при одном и том же результате на сервере. Другими словами, создание большого количества идентичных запросов имеет такой же эффект, как и один запрос. Заметьте, что в то время, как идемпотентные операции производят один и тот же результат на сервере, ответ сам по себе может не быть тем же самым (например, состояние ресурса может измениться между запросами).

Методы PUT и DELETE по определению идемпотентны. Тем не менее, есть один нюанс с методом DELETE. Проблема в том, что успешный DELETE-запрос возвращает статус 200 (OK) или 204 (No Content), но для последующих запросов будет все время возвращать 404 (Not Found), Состояние на сервере после каждого вызова DELETE то же самое, но ответы разные.

По определению, безопасные операции идемпотентны, так как они приводят к одному и тому же результату на сервере. Безопасные методы реализованы как операции только для чтения. Однако безопасность не означает, что сервер должен возвращать тот же самый результат каждый раз.

Анатомия запроса

Важно понимать структуру запроса:

  1. Маршрут отправки - это адрес, по которому отправляется ваш запрос. Например: https://api.github.com/
  2. Тип метода - обозначает тип производимого запроса,он является спецификацией операции, которую должен произвести сервер: GET, POST, PUT, PATCH, DELETE ...
  3. Заголовки - используются, чтобы предоставить информацию как клиенту, так и серверу. Вообще, их можно использовать для много чего – пример – та же самая аутентификация и авторизация. Найти список доступных заголовком можно на официальной странице MDN. Заголовки представляют из себя пары ключей-значений.
  4. Тело (или данные) - данные, которые отправляются в запросе

Тестирование при помощи Curl

Вы можете отправить запрос при помощи любого инструмента, описанного выше (например, JMeter/Postman) Также вы можете отправить запрос при помощи любого языка программирования: JavaScript/Ruby и т.д.

Мы будем пока использовать утилиту Curl. Так как она указана в официальной документации для веб-сервисов. Если вы поймете, как использовать эту утилиту, вы поймете, как работать с API. После чего вы можете производить запросы любым удобным для вас языком программирования. Перед тем, как продолжить, вам следует убедится, что Curl установлен на вашей машине (или установите отсюда).

$ curl --version
curl 7.58.0 (x86_64-w64-mingw32) libcurl/7.58.0 OpenSSL/1.0.2n (WinSSL) zlib/1.2.11 libidn2/2.0.4 nghttp2/1.29.0
Release-Date: 2018-01-24
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smtp smtps telnet tftp
Features: AsynchDNS Debug IDN IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL libz TLS-SRP HTTP2 HTTPS-proxy 
MultiSSL Metalink

Работоспособность проверим командой curl https://api.github.com (в наших примерах мы будем использовать GitHubAPI) : Ниже приведены некоторые примеры запросов к разным API с помощью curl и браузера (Chrome/Firefox). Кстати потренироваться с разными открытыми API Вы сможете здесь

curl Chrome
запрос к API curl https://api.github.com/ 1
ответ от API 1 1
запрос к API curl -X GET "https://date.nager.at/Api/v1/Get/BY/2020" 1
ответ от API [{"date":"2020-01-01","localName":"Новы год","name":"New Year's Day",... 1