Привет любителям котиков! Меня зовут Юля, я backend‑разработчик компании CDEK. Я сама не так давно изучала все эти сложные понятия в программировании, поэтому решила помочь и вам разобраться с одним из них.

С какой стороны IT вы бы не пытались войти — в какой‑то момент столкнётесь с понятием REST API. Эта статья создана, чтобы смягчить данное столкновение. Новые темы всегда легче воспринимаются на простых примерах, ну а если это примеры с котиками, то варианта не разобраться просто нет. Хочется обойтись без сложных научных определений, а рассказать самым простым языком. Поэтому, если вы любите сухие и точные формулировки, то вам нужна другая статья :)

Содержание

Знакомьтесь, REST API и Шани

Если очень просто описать, то

REST API — это правила общения сервисов (если ещё проще — программ) в интернете.

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

Супер, теперь давайте узнаем, какие именно это правила и заодно запишем нашего котика Шани (знакомьтесь!) на участие в Котовыставке. Так сказать, совместим приятное с полезным.

У Котовыставки, конечно же, есть сайт в интернете с удобным для пользователя интерфейсом. Но этот интерфейс не умеет отправлять информацию серверу, потому что сервер понимает только на «своём языке».

Наш красивый интерфейс, который видит пользователь сайта, мы будем называть клиентом, а сервером может быть любой компьютер, умеющий обрабатывать информацию от клиента.

Правила работы с REST API

Первое правило REST API как раз про это: пользовательский интерфейс является отдельной программой от сервера, на котором будет обрабатываться информация. Очень легко запомнить такую аналогию: тот, кто информацию запрашивает — это клиент, а тот, кто на запрос отвечает — сервер.

Второе правило заключается в том, что каждый новый запрос от клиента не зависит от состояния других запросов. Если мы решим записать двух котиков на участие в выставке, то, заполняя анкету, мы должны каждый раз указывать полную информацию в форме записи. Даже если информация повторяется, мы не можем сослаться на ту анкету, что уже была отправлена, мол, «возьмите из прошлого запроса» — так это работать не будет.

После того, как мы отправили запрос (с первой анкетой), мы уже ничего не знаем о его существовании и содержании, потому что не храним эту информацию на клиенте.

Третье правило говорит, что клиент может сохранить у себя в памяти какую‑то редко изменяющуюся информацию от сервера на определённое время, тем самым снизив количество запросов к серверу. Например, у нас на сайте Котовыставки есть правила участия. Меняются они крайне редко, поэтому клиент может запросить их один раз и сохранить у себя в памяти, чтобы каждый раз, когда пользователь решит их прочитать, клиенту не нужно было делать запрос к серверу.

Четвёртое правило обязывает нас использовать определённый стиль общения между клиентом и сервером. А точнее, определённый протокол, который называется HTTP. Если у вас, как и у меня, при виде странного набора английских букв появляется мандраж, не пугаемся: HTTP — это всего лишь набор договорённостей о том, как передавать информацию между двумя программами в интернете.

В самом начале статьи я сказала, что пока что клиент не умеет отправлять запросы на сервер, потому что сервер понимает только «на своём языке». Давайте же научим их общаться и сами разберёмся в этих правилах общения. 

Формируем запросы

Есть набор действий, которые может выполнить сервер. Они строго ограничены несколькими словами, такими как GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH. Включаем наш пёфект инглиш и переводим, что за действия нам предлагаются. Рассматривать будем не все, а только самые распространённые: GET, POST, PUT, DELETE.

Мы уже видели, что на главной странице сайта Котовыставки есть кнопка «Участники Котовыставки». Предлагаю посмотреть конкурентов, прежде чем записывать нашего котика. Мы, как пользователи, ожидаем, что по нажатию этой кнопки нам покажут всех участников. А как будет выглядеть запрос от клиента к серверу?

Ура, запрос мы отправили! Давайте кратко разберём, из чего он состоит: 

  • GET — это то действие, которое мы хотим, чтобы выполнил сервер (называется метод запроса).

  • Host: catshow.com — адрес сайта Котовыставки в интернете.

  • /cats — уникальный путь на сайте, по которому находится список участников Котовыставки.

  • HTTP/1.1 — это версия используемого протокола.

А теперь посмотрим, какой будет ответ:

В ответе от сервера видим уже знакомую нам версию HTTP‑протокола (подчёркнуто красным цветом).

А теперь посмотрим на то, что пока нам не знакомо:

  • 200 OK — это статус ответа от сервера. Даже если бы он не прислал всё остальное, то уже по этому статусу клиент мог бы определить, что запрос успешно обработан. Список статусов и их значения разберём ниже.

  • Content‑Type и Content‑Length — это заголовки ответа, а после двоеточия — их значения. В этом примере Content‑Type сообщает нам, в каком формате придёт ответ от сервера, в данном случае это JSON (самый распространённый формат). А Content‑Length указывает на размер отправленного тела объекта в байтах. Заголовков достаточно много — каждый раз, когда вы будете сталкиваться с неизвестным вам заголовком, обращайтесь к поисковику.

  • Тело запроса — это та информация, которую клиенту нужно отобразить в удобном для восприятия пользователя виде. В нём сервер прислал информацию о трёх котиках, и то же самое видим в интерфейсе сайта.

Конкурентов посмотрели, поняли, что с нашим котиком никто не сравнится. Решаем записать его на Котовыставку. Будем заполнять анкету участника и отправлять её на сервер.

В запросе видим уже больше знакомых элементов, например: версию HTTP‑протокола, адрес сайта, уникальный путь. Особо внимательные читатели могут спросить, почему же он уникальный, ведь строка запроса в браузере будет выглядеть так же, как в первом запросе, который мы рассматривали: catshow.com/cats. И это действительно так, а уникальность запроса будет обеспечивать метод. Как видите, действие стало POST. Главное различие между GET и POST‑запросом заключается в наличии тела запроса во втором случае. В нём передаётся информация, которую клиент хочет послать на сервер. Также видим и заголовки запроса, которые очень похожие на те, что мы уже видели в ответе сервера. В целом, это они и есть, только теперь называются заголовками запроса.

А вот и ответ сервера на предыдущий запрос:

Проверьте себя: вспомните, о чём я рассказала выше, и назовите элементы, из которых состоит ответ сервера.

Что видим нового в этом ответе — заголовок Location. Он сообщает клиенту, по какому уникальному пути была сохранена информация из запроса. Нашему котику, которого мы записали на Котовыставку, присвоен номер 4. Также видим, что в ответе нет тела. Как клиент поймёт, что анкета участника сохранена? Правильно, по коду ответа 201 Created. Это как раз и говорит клиенту о том, что запрос прошёл успешно, запись об участнике создана.

Давайте посмотрим информацию о нашем котике, которого мы записали — отправим соответствующий запрос.

Запрос очень похож на первый, в котором мы получали список всех котиков. Разница в том, что уникальный путь запроса изменился, теперь он стал /cats/4. Тем самым мы показываем, что хотим не список котиков получить, а информацию о номере 4.

А теперь посмотрим на ответ:

Ну вот, уже и удивить вас нечем, всё в ответе вам знакомо.

Котика мы записали, а вот контакты указали неправильно. Давайте поправим эту информацию и отправим соответствующий запрос.

Тут обратим внимание на метод запроса — это PUT. Самое распространённое его использование — обновление данных.

Посмотрим на ответ:

Обновление прошло успешно, клиент понимает это по коду ответа от сервера. 204 No Content говорит о том, что запрос выполнен успешно и никакой контент в ответ не отправлен.

Думали мы с вами, думали и передумали, чтобы Шани участвовал в Котовыставке. Решили удалить его анкету. Давайте посмотрим, как будет выглядеть такой запрос.

Запрос очень похож на GET, уникальный путь у нас совпадает: /cats/4. Но метод запроса скажет серверу, какое именно действие (DELETE) мы хотим выполнить с анкетой котика номер 4.

Поздравляю! Вы только что разобрались, как работает простое CRUD‑приложение. CRUD, кстати, расшифровывается, как «create, read, update, delete». Как раз все те операции, которые мы разобрали.

Коды ответов сервера

Теперь расскажу про коды ответов сервера. Как вы уже обратили внимание, везде сервер нам отдавал разные модификации статуса 200.

2xx — любые двухсотые коды статуса свидетельствуют о том, что запрос был успешно обработан сервером. Котик сохранился, обновился, удалился, ну вы поняли.

3xx — трёхсотые коды говорят о том, что нам необходимо перенаправить наш запрос по другому адресу, обычно сервер сообщает, по какому именно. Если, например, сайт Котовыставки поменяет свой адрес в интернете с catshow.com на thebestcatshow.com, то мы хотели бы узнать об этом и перенаправить наш запрос.

4xx — четырёхсотые статусы ответа возвращаются, если произошла какая‑то ошибка на стороне клиента. Например, если в поле для ввода номера телефона вы напишите своё имя, сервер, вероятно, это заметит и попросит вас исправить.

5хх — пятисотые статусы — это признак того, что сервер, который должен был обрабатывать информацию, больше недоступен. Например, если во всем городе отключили электричество (или именно в том подвале, где стоит наш компьютер‑сервер). 

В общем, можно запомнить, что чем больше код статуса, тем ситуация хуже. Исходя из этого утверждения, попробуйте предположить, что могут означать код статуса 100 и 600 (вопрос с подвохом)? Жду ваши ответы в комментариях :)

Комментарии (18)


  1. paveltyurikov
    25.04.2024 17:14
    +6

    REpresentational State Transfer ни словечка про это. Таким образом первое правило не существует.
    Второе правило про HTTP, но не про REST
    Третье правило про кэширование, но не про REST
    Четвертое правило - протокол (HTTP) и архитекnрутный стиль (REST), как следует из википедии, не одно и то же. Не стоит путать тёплое с мягким. Правила протокола нарушать нельзя, архитектурные правила, можно, если очень захотеть.
    И далее всё про HTTP, а не про REST.
    И это ещё никто не упомянул про RESTful


    1. nronnie
      25.04.2024 17:14
      +7

      По-моему, у автора вполне соответствует тому что написано в оригинале - немного своими словами, но достаточно близко.


  1. ValeryGL
    25.04.2024 17:14
    +3

    Пролистав первую половину статьи, возрадовался - рассказано просто, правильно и главное - без всяких джисонов и хттп! Ан нет, появились потом..
    По существу: классная статья, рассказано именно базовые вещи без воды и отвлечение. Автор - крутая! Дай пожму лапу


    1. Rsa97
      25.04.2024 17:14
      +1

      А без HTTP и JSON не получится, REST на них жёстко завязан, прибит, так сказать, гвоздями.


      1. nronnie
        25.04.2024 17:14
        +1

        Строго говоря нет. В оригинальной работе Роя Филдинга, который в ней первым сформулировал принципы REST (и на которую я выше приводил ссылку) HTTP приводится только как пример протокола по которому могут взаимодействовать части распределенной REST-системы, но какого-то прямого требования, что этим протоколом может быть только HTTP вовсе нет.


        1. Rsa97
          25.04.2024 17:14
          +2

          Прямого требования нет. Но когда вы в последний раз видели, например, REST на XML поверх вебсокетов или REST с бинарными данными поверх MQTT?
          В работе Филдинга, кстати, в примерах коннекторов и компонентов (таблицы 5-2 и 5-3) тоже сплошь HTTP-серверы и клиенты.


    1. JulieMatveeva Автор
      25.04.2024 17:14
      +1

      Спасибо большое за поддержку:)
      Я бы хотела объяснить без json и http, но начинающие специалисты разбирая эту тему все равно бы о них споткнулись)


  1. rrash84
    25.04.2024 17:14
    +1

    Статья больше похожа на "http для дошколят"


  1. Harpagon
    25.04.2024 17:14

    А мы точно получим ответ и статус от сервера, если он выключен? Статья действительно больше описывает протокол http, чем REST.


    1. JulieMatveeva Автор
      25.04.2024 17:14
      +1

      Если сервер отключен или недоступен, то обычно будет отображаться сообщение ошибки "504 Gateway Timeout" или "503 Service Unavailable". Эти ошибки указывают на то, что сервер не отвечает на запросы вовремя из-за проблем соединения или отказа сервера обрабатывать запросы. Также может отображаться сообщение о том, что "страница не может быть загружена" или что "сайт недоступен". В любом случае, если сервер отключен, пользователи не смогут получить доступ к сайту до тех пор, пока сервер снова не станет доступен.


  1. Siddthartha
    25.04.2024 17:14

    Думали мы с вами, думали и передумали, чтобы Шани участвовал в Котовыставке. Решили удалить его анкету. Давайте посмотрим, как будет выглядеть такой запрос.


    Юля, может проще табличкой?)


    1. JulieMatveeva Автор
      25.04.2024 17:14

      А что именно табличкой? Не совсем поняла, если напишите подробнее, то учту это на будущее)


  1. Ib1za
    25.04.2024 17:14
    +2

    Котики это топ в любом случае, одобряю:D


  1. N1kk0n
    25.04.2024 17:14

    Вопрос: а как в соответствии с этими правилами должен выглядеть запрос, возвращающий котиков породы мейн-кун и британских вислоухих, отсортированных по возрасту и числу призов?


    1. nronnie
      25.04.2024 17:14
      +1

      Например:

      GET /api/cats/?$filter=Breed in('мейн-кун', 'британский вислоух')&$orderby=(Age, PrizeCount)
      


      1. Vladimir0x29A
        25.04.2024 17:14
        +1

        Скорее так

        GET /api/cats?breed[]=maine_coon&breed[]=british_fold&$order_by[0]=age&order_by[1]=prize_count


      1. JulieMatveeva Автор
        25.04.2024 17:14
        +1

        Например вот так
        GET api/cats?breed=maine-coon,british-shorthair&sort=age,prizes


        1. Vladimir0x29A
          25.04.2024 17:14

          Такой запрос, конечно, можно сформировать при помощи скрипта на фронтэнде и даже распарсить его на бэкэнде, применив, возможно, не самый стандартный подход, но подумайте, как будет выглядеть запрос с применением обычной html-формы и таких тегов, как <input type="ckeckbox"> или <select multiple>. У этих элементов будут атрибуты name и value, что будет значить "ключ" и "значение", отражаемые в запросе, и применение одинаковых имён позволит последним выбранным значениям перезаписать предыдущие.