Клиент-серверная двухуровневая архитектура ис. Хорошая клиент-серверная архитектура

  • Разработка под iOS ,
  • Разработка мобильных приложений
  • Сразу оговорюсь, что я мобильный разработчик, а статья предназначается в основном разработчикам по ту сторону облака - мобильщики итак про все это знают. Последнее веб-приложение я писал много лет назад и могу ошибаться в веб-терминологии, не знать некоторых последних тенденций.NET-, PHP- или Java- веб-сервисов, так что не судите строго.

    Как и любому front-end разработчику, мне почти в каждом проекте приходится сталкиваться с клиент-серверными протоколами – без них никак. И очень, крайне часто приходится работать с плохо продуманной архитектурой.

    Также очень часто разработка протокола и архитектуры ложится на плечи веб-разработчика, что не всегда верно – она в большинстве случаев должна разрабатываться только совместно с теми, кто под эту архитектуру будет подстраиваться. К сожалению, работая за последние три года на нескольких десятках проектов, мне доводилось участвовать в планировании этого участка архитектуры только 3 или 4 раза – во всех остальных случаях она уже была предоставлена в разной степени готовности заказчиком. А ведь насколько мир мог бы быть лучше!

    Обработка ошибок

    Чаще всего мне попадалось что-то вроде этого:

    HTTP code 200 (OK) false The username or password is incorrect. Please try again.
    Т.е. результат обработки запроса содержится в самом отдаваемом XML, HTTP-код возврата – 200, т.е. нормально, данные представлены в виде обычного RPC. Например, похожим образом в 90% случаев реализуется обработка ошибок в протоколе SOAP.

    В особо запущенных случаях, особенно характерных для индусского кода, false может находиться в различных местах XML, что существенно усложняет парсинг, ведёт к переусложнённым и безмерно радует скучающего программиста.

    Но давайте рассмотрим недостатки данного подхода в принципе.

    • Во-первых, приходится парсить XML. Это лишние данные, переданные по сети, лишнее процессорное время, затраченное на парсинг XML, лишняя оперативная память для хранения текстовых данных. Всё это не так страшно на современных девайсах в зоне Wi-fi, но даже такие излишества могут иметь значение в метро между станциями в приложении, посылающем одновременно десятки запросов (а ведь при таком подходе пустые блоки для обработки ошибок должны быть в каждом запросе, даже успешном).
    • Во-вторых, веб-разработчику приходится самому выдумывать тексты ошибок. Очень часто они совершенно непонятны пользователю, т.к. точность формулировки – последнее, о чём думает веб-разработчик в момент написания сервиса. Текст ошибки в 90% случаев не согласовывается с native-спикерами и последнее, но самое важное – огромное количество мобильных приложений нуждается в локализации. В то время как текст ошибки, скорее всего, пишется всегда только по-английски, следовательно он абсолютно бесполезен для фронтэнд-программиста – он не может его просто взять и вывести.

    А ведь время, нужное веб-программисту, чтобы выдумать текст сообщения, потрачено впустую, да ещё и канал загружен ненужной информацией.

    Как решить проблему?

    В протоколе HTTP уже много лет заложена возможность добавлять свои коды ошибок, для этого они просто должны принадлежать диапазону от 512 до 597. Такого количества ошибок, я уверен, хватит для покрытия всех возможных ошибок в приложении среднего размера. Очевидно, какие плюсы это даёт, но всё же подытожим:

    1. Нет избыточности. Передаётся только HTTP код в хэдере, тела запроса просто нет.
    2. На стороне клиента существуют только две ветки кода обработки запросов – успешное выполнение, либо ошибка при выполнении (оба колбэка уже имплементированы из коробки в любой библиотеке запросов). Нет веток “запрос выполнился успешно, но логическая ошибка может быть в теле ответа”.
    5xx Server Error

    The server failed to fulfill an apparently valid request.
    Response status codes beginning with the digit «5» indicate cases in which the server is aware that it has encountered an error or is otherwise incapable of performing the request. Except when responding to a HEAD request, the server should include an entity containing an explanation of the error situation, and indicate whether it is a temporary or permanent condition. Likewise, user agents should display any included entity to the user. These response codes are applicable to any request method.

    Т.е. клиенты должны показывать пользователю сообщение, переданное сервером. Сразу видно, что писали американцы. Русские, кстати, тупо перевели .

    Хотя не будем обобщать – идею использовать HTTP коды мне подсказал как раз-таки американец несколько лет назад.

    В общем, идеология такая - клиент всегда лучше знает, как сообщить об ошибке. А сервер должен проинформировать клиент об ошибке самым быстрым и малозатратным способом.

    Привязка к сессии или cookie.

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

    Вторым, глобальным недостатком является то, что Safari (или любой браузер на Android) не шарят свои cookie и переменные сессии с приложением, что, конечно, правильно с точки зрения секьюрности, но приводит к ряду проблем и костылей.

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

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

    Вывод – если вы проектируете универсальный протокол, забудьте про такие вещи как переменные сессии и cookie. Намного лучшим способом будет передавать некий уникальный токен, полученный при авторизации, явно в теле каждого запроса. А веб-страницам и веб-приложениям – подстроиться под использование единого API. Я уверен, все мобильные разработчики часто видели две версии API – одно для веб-приложений, другое – для мобильных. А ведь это – дублирование функционала, которое всегда дороже как на этапе разработки, так и на этапе отладки. Лучше всегда с самого начала выделять веб-сервисы в отдельный слой системы, а не встраивать в другие, близкие к веб-технологиям, части.

    Возврат HTML

    Это уже ведёт корнями к устройству самих веб-серверов, которые изначально были заточены только под браузер. Ошибки 403, 404, а порой и более сложные очень часто отдаются в виде HTML-страницы, которую зачастую просто нет средств показать в мобильном приложении. Точнее, средства есть, но увидев “404 page not found” здоровенным черным Arial Black на белом фоне внутри веб-вью, мобильный пользователь испугается и закроет приложение.

    Запомните, сервер на любое обращение к веб-сервисам должен отдавать XML (или JSON), и только в том формате, который был изначально оговорен. Мобильный разработчик не может сделать ничего путного с HTML, который приходит с сервера.

    Используйте WSDL

    На майкрософтовский технологиях ситуация еще ничего - большинство их современных технологий поддерживает WSDL из коробки. Чего не скажешь про PHP и Java - особенно PHP-разработчики очень любят создавать вручную обычные странички, которые по сути являются веб-сервисами. А ведь для того, чтобы интегрироваться с WSDL-совместимым веб-сервисом, мобильному разработчику достаточно использовать тулзу для генерации кода, в то время как составленные «вручную» ответы веб-сервисов тоже нужно парсить «руками».

    Правда, и здесь есть тонкости - стандартные реализации WSDL от MS и Sun (Oracle) всё-таки имеют несовместимости, но все же быстрее подправить напильником эти несовместимости, чем писать все вручную.

    Заключение

    Я затронул только самые наболевшие ошибки проектирования, с которыми изо дня в день приходится сталкиваться мобильным разработчикам. Если статья будет востребованной, я обязательно напишу ещё о десятке клиент-серверных тонкостей, которые очень хотелось бы видеть в API веб-сервисов, с которыми работаешь каждый день.

    Независимо от того, как определяется понятие архитектуры «клиент-сервер» (а таких определений в литературе много), в основе этого понятия лежит распределенная модель вычислений. В самом общем случае под клиентом и сервером понимаются два взаимодействующих процесса, из которых один является поставщиком некоторого сервиса для другого.

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

    Сервер — один или несколько многопользовательских процессоров с единым полем памяти, который в соответствии с потребностями пользователя обеспечивает им функции вычисления, коммуникации и доступа к базам данных. Сервер можно назвать программу, представляющая какие-то услуги другим программам. Примеры серверов - вебсервер Apache, серверы баз данных - MySQL, ORACLE, сетевые файловые системы и принтера Windows.

    Клиент — рабочая станция для одного пользователя, обеспечивающая режим регистрации и др. необходимые на его рабочем месте функции вычисления, коммуникацию, доступ к базам данных и др. Клиентом можно назвать это программа, использующая услугу, представляемую программой сервера. Примеры клиентов - MSIE (MS Internet Explorer), клиент ICQ.

    Часто люди клиентом или сервером просто называют компьютер, на котором работает какая-то из этих программ.

    В сущности клиент и сервер - это роли, исполняемые программами. Клиенты и сервера физически могут находиться на одном компьютере. Одна и та же программа может быть и клиентом, и сервером одновременно, и т.д… это только роли.

    Если проводить аналогию с обществом - банк или магазин - «сервера». Они представляют какие-то услуги своим клиентам. Но банк может в то же время быть клиентом какой-то другой фирмы и т. д…

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

    СУБД с персональных ЭВМ (такие, как Clipper, DBase, FoxPro, Paradox, Clarion имеют сетевые версии, которые просто совместно используют файлы баз данных тех же форматов для ПК, осуществляя при этом сетевые блокировки для разграничения доступа к таблицам и записям. При этом вся работа осуществляется на ПК. Сервер используется просто как общий удаленный диск большой емкости. Такой способ работы приводит к риску потери данных при аппаратных сбоях.

    По сравнению с такими системами системы, построенные в архитектуре Клиент — Сервер, имеют следующие преимущества:

      позволяют увеличить размер и сложность программ, выполняемых на рабочей станции;

      обеспечивает перенесение наиболее трудоемких опе-раций на сервер, являющийся машиной большей вычислительной мощности;

      уменьшает до минимума возможность потери содержащейся в БД информации за счет применения имеющихся на сервере внутренних механизмов защиты данных, таких, как, например системы трассировки транзакций, откат после сбоя, средства обеспечения целостности данных;

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

      В архитектуре «клиент-сервер» сервер базы данных не только обеспечивает доступ к общим данным, но и берет на себя всю обработку этих данных. Клиент посылает на сервер запросы на чтение или изменение данных, которые формулируются на языке SQL. Сервер сам выполняет все необходимые изменения или выборки, контролируя при этом целостность и согласованность данных, и результаты в виде набора записей или кода возврата посылает на компьютер клиента.

      Она позволяет оптимальным образом распределить вычислительную нагрузку между клиентом и сервером, что также влияет на многие характеристики системы: стоимость, производительность, поддержку.

      1.2. История…

      Архитектура и термин «клиент-сервер» впервые использовались в начале 80-тых годов. Первые приложения с архитектурой «клиент-сервер» были базы данных.

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

      Тогда придумали, что удобно поставить базу данных на мощном отдельном компьютере (сервере) и разрешить эту базу данных использовать многим пользователям малого компьютера (клиентам) через сеть, что и было сделано.

      По существу «взрыв» популярности технологии «клиент-сервер» был вызван изобретением фирмой IBM простого языка запросов к реляционным базам данных SQL. Сегодня SQL всеобщий стандарт работы с базами данных. В последнее время этот «взрыв» продолжает изобретение Интернета, в котором буквально каждое взаимодействие происходит по архитектуре «клиент-сервер».

      1.3. Протоколы

      Сервер и клиент в сети между собой «разговаривает» на «языке» (в широком смысле слов), понятном обеим сторонам. Этот «язык» называют протоколом.

      В случае банка, протоколом можно назвать бланки, которые заполняет клиент.

      В нашем же случае, примеры протоколов:

      FTP (File Transfer Protocol)

      HTTP (Hyper Text Transfer Protocol)

      SMTP (Simple Mail Transfer Protocol)

      IP (Internet Protocol)

      MySQL Client/Server Protocol

      Заметим, что протоколы может быть разных уровней. Классификационные системы уровней может быть разные, но одна из самых известных линеек - OSI (Open Systems Interconnection), в котором 7 уровней.

      Например, HTTP - протокол прикладного (седьмого - самого высокого) уровня, а IP - протокол сетевого (третьего) уровня.

      1.4. Распределение функций в архитектуре «клиент-сервер»

      В классической архитектуре клиент-сервер приходится распределять три основные части приложения по двум физическим модулям. Обычно ПО хранения данных располагается на сервере (например, сервере базы данных), интерфейс с пользователем — на стороне клиента, а вот обработку данных приходится распределять между клиентской и серверной частями. В этом-то и заключается основной недостаток двухуровневой архитектуры, из которого следуют несколько неприятных особенностей, сильно усложняющих разработку клиент-серверных систем.

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

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

      Основные функции серверной СУБД - обеспечение надежности, согласованности и защищенности данных, управление запросами клиентов, быстрая обработка SQL-запросов.

      Вся логика работы приложения - прикладные задачи, бизнес-правила - в двух-звенной архитектуре распределяются разработчиком между двумя процессами: клиентом и сервером (рис. 1).

      Сначала большая часть функций приложения решалась клиентом, сервер занимался только обработкой SQL-запросов. Такая архитектура получила название «толстый клиент - тонкий сервер».

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

      Такое решение имеет очевидные преимущества, например его легче поддерживать, т. к. все изменения нужно вносить только в одном месте - на сервере.

      рассмотренные выше модели имеют следующие недостатки.

      1. «Толстый» клиент:

      – сложность администрирования;

      – усложняется обновление ПО, поскольку его замену нужно производить одновременно по всей системе;

      – усложняется распределение полномочий, так как разграничение доступа происходит не по действиям, а по таблицам;

      – перегружается сеть вследствие передачи по ней необработанных данных;

      – слабая защита данных, поскольку сложно правильно распределить полномочия.

      2. «Толстый» сервер:

      – усложняется реализация, так как языки типа PL/SQL не приспособлены для разработки подобного ПО и нет хороших средств отладки;

      – производительность программ, написанных на языках типа PL/SQL, значительно ниже, чем созданных на других языках, что имеет важное значение для сложных систем;

      – программы, написанные на СУБД-языках, обычно работают недостаточно надежно; ошибка в них может привести к выходу из строя всего сервера баз данных;

      – получившиеся таким образом программы полностью непереносимы на другие системы и платформы.

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

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

      Тогда возникла тенденция поручить выполнение прикладных задач и бизнес-правил отдельному компоненту приложения (или нескольким компонентам), которые могут работать как на специально выделенном компьютере - сервере приложений, так и на том же компьютере, где работает сервер базы данных. Так возникли трехзвенные и многозвенные архитектуры «клиент-сервер».


      Рис. 1. Распределение функций между клиентом и сервером

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


      СПИСОК ИСПОЛЬЗУЕМОЙ ЛИТЕРАТУРЫ

    1. Информатика / Под ред. Н.В. Макаровой.–М.: Финансы и статистика, 1998.

      Евдокимов В.В. и др. Экономическая информатика. СПб.: Питер, 2004.

      Казаков С.И. Основы сетевых технологий – М.: Радио и связь, 2004.

      Когаловский М.Р., Технология баз данных на персональных ЭВМ, – М.: Финансы и статистика, 2003.

      Попов В.В. Основы компьютерных технологий. –М.: Финансы и статистика, 2001.

      Фигурнов В.Э. IBM PC для пользователя. М., 2000.

    ОПЕРАЦИОННАЯ СИСТЕМА MS-DOS . ОСНОВНЫЕ ПОНЯТИЯ И КОМАНДЫ ОСНОВНЫЕ ПОНЯТИЯ: БАЗА ДАННЫХ, СУБД, СУЩНОСТЬ, АТРИБУТ, СВЯЗЬ (ОДИН-К-ОДНОМУ, ОДИН-КО-МНОГИМ, МНОГИМ-КО-МНОГИМ), ОТНОШЕНИЕ, ПЕРВИЧНЫЙ КЛЮЧ

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

    Клиент-серверная архитектура

    Архитектура «Клиент-Сервер» представляет собой взаимодействие структурных компонентов в сети на основе определенных данной сети, где структурными компонентами являются сервер и узлы-поставщики определенных специализированных функций (сервисов), а также клиенты, которые пользуются данным сервисом. Специфические функции принято делить на три группы на основе решения определенных задач:

    • функции ввода и представления данных предназначены для взаимодействия пользователя с системой;
    • прикладные функции - для каждой имеется собственный набор;
    • функции управления ресурсами предназначены для управления файловой системой, различными базами данных и прочими компонентами.

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

    Принцип работы клиент-серверной архитектуры

    Клиент-серверная архитектура наиболее часто используется для создания корпоративных баз данных, в которых информация не только хранится, но и периодически поддается обработке различными методами. Именно база данных является главным элементом любой корпоративной информационной системы, а на сервере располагается ядро этой базы. Так, на сервере происходят наиболее сложные операции, касающиеся ввода, хранения, обработки и модификации данных. Когда пользователь (клиент) обращается к базе данных (серверу), происходит обработка запроса: непосредственно обращение к базе данных и возврат ответа (результата обработки). Результат обработки - это сообщение сети об успешном проведении операции или ошибке. Серверные компьютеры могут обрабатывать одновременно обращение нескольких клиентов к одному и тому же файлу. Такая работа и по сети позволяет ускорить работу используемых приложений.

    Клиент-серверная архитектура: применение технологии

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

    Клиент-серверная двухуровневая архитектура ИС

    Ключевым отличием архитектуры клиент-сервер от архитектуры файл-сервер является абстрагирование от внутреннего представления данных (физической схемы данных). При такой архитектуре клиентские программы манипулируют данными на уровне логической схемы. Для реализации архитектуры клиент-сервер обычно используют многопользовательские СУБД, например, Oracle или Microsoft SQL Server.

    Клиент-серверная информационная система состоит из трех основных компонент: программное обеспечение сервера; программное обеспечение конечного пользователя; промежуточное программное обеспечение (рис.1.7). Программное обеспечение сервера, кроме управления базами данных обеспечивает обслуживание клиентов.

    В таких СУБД предусмотрены механизмы блокировки и элементы управления многопользовательским доступом, которые обеспечивают защиту данных от рисков, присущих параллельному доступу. Кроме этого, серверу баз данных приходится защищать данные от несанкционированного доступа, оптимизировать запросы к базе данных, обеспечивать целостность данных и контроль завершение транзакций. В клиент-серверной организации клиенты могут быть достаточно "тонкими", а сервер должен быть "толстым" настолько, чтобы удовлетворять потребности всех клиентов.К программному обеспечению конечного пользователя относятся средства разработки прикладных программ и генераторы отчетов, в том числе электронные таблицы и текстовые процессоры С помощью этого программного обеспечения пользователи устанавливают связь с сервером, формируют запросы, которые автоматически генерируются в запросы на языке SQL и отправляются на сервер. Сервер принимает и обрабатывает запросы, а затем передает полученные результаты клиентам. Промежуточное программное обеспечение ― часть системы клиент-сервер, которая связывает программное обеспечение конечного пользователя с сервером.

    Использование архитектуры клиент-сервер позволило создавать надежные (в смысле целостности данных) многопользовательские ИС с централизованной базой данных, независимые от аппаратной (а часто и программной) части сервера БД и поддерживающие графический интерфейс пользователя на клиентских станциях, связанных локальной сетью. Причем издержки на разработку приложений существенно сокращались.

    Такая архитектура имеет два уровня, характерной особенностью которой является то, что клиентские программы работает с данными через запросы к серверному ПО, а базовые функции приложения разделены между клиентом и сервером (рис.1.8).

    К достоинствам этой архитектуры относятся:

    · полная поддержка многопользовательской работы;

    · обеспечение целостности данных.

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

    Недостатками двухуровневой клиент-серверной архитектуры являются:

    · Бизнес логика приложений осталась в клиентском ПО. При любом изменении алгоритмов, надо обновлять пользовательское ПО на каждом клиенте.

    · Высокие требования к пропускной способности коммуникационных каналов с сервером, что препятствует использование клиентских станций иначе как в локальной сети.

    · Слабая защита данных от взлома, в особенности от недобросовестных пользователей системы.

    · Высокая сложность администрирования и настройки рабочих мест пользователей системы.

    · Необходимость использовать мощные ПК на клиентских местах.

    · Высокая сложность разработки системы из-за необходимости выполнять бизнес-логику и обеспечивать пользовательский интерфейс в одной программе.

    Рассказывает Владимир, веб-разработчик Noveo

    Большинству разработчиков сайтов, веб-сервисов и мобильных приложений рано или поздно приходится иметь дело с клиент-серверной архитектурой, а именно разрабатывать web API или интегрироваться с ним. Чтобы не изобретать каждый раз что-то новое, важно выработать относительно универсальный подход к проектированию web API, основываясь на опыте разработки подобных систем. Предлагаем вашему вниманию объединенный цикл статей, посвящённых этому вопросу.

    Приближение первое: Действующие лица

    В один прекрасный момент, в процессе создания очередного веб-сервиса, я решил собрать все свои знания и размышления на тему проектирования web API для обслуживания нужд клиентских приложений и оформить их в виде статьи или серии статей. Разумеется, мой опыт не претендует на абсолют, и конструктивная критика и дополнения более чем приветствуются.

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

    Клиент и сервер

    Сервером в данном случае мы считаем абстрактную машину в сети, способную получить HTTP-запрос, обработать его и вернуть корректный ответ. В контексте данной статьи совершенно не важны его физическая суть и внутренняя архитектура, будь то студенческий ноутбук или огромный кластер из промышленных серверов, разбросанных по всему миру. Нам в той же мере совершенно неважно, что у него под капотом, кто встречает запрос у дверей, Apache или Nginx, какой неведомый зверь, PHP, Python или Ruby выполняет его обработку и формирует ответ, какое хранилище данных используется: Postgresql, MySQL или MongoDB. Главное, чтобы сервер отвечал главному правилу - услышать, понять и простить ответить.

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

    По большей части мы будем говорить о способе общения между выше перечисленными двумя, таком способе, чтобы они друг друга понимали, и ни у одного не оставалось вопросов.

    Философия REST

    REST (Representational state transfer) изначально был задуман как простой и однозначный интерфейс для управления данными, предполагавший всего несколько базовых операций с непосредственным сетевым хранилищем (сервером): извлечение данных (GET), сохранение (POST), изменение (PUT/PATCH) и удаление (DELETE). Разумеется, этот перечень всегда сопровождался такими опциями, как обработка ошибок в запросе (корректно ли составлен запрос), разграничение доступа к данным (вдруг этого вам знать не следует) и валидация входящих данных (вдруг вы написали ерунду), в общем, всеми возможными проверками, которые сервер выполняет перед тем, как выполнить желание клиента .

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

    Независимость сервера от клиента - серверы и клиенты могут быть мгновенно заменены другими независимо друг от друга, так как интерфейс между ними не меняется. Сервер не хранит состояний клиента.
    Уникальность адресов ресурсов - каждая единица данных (любой степени вложенности) имеет свой собственный уникальный URL, который, по сути, целиком является однозначным идентификатором ресурса.

    Пример: GET /api/v1/users/25/name

    Независимость формата хранения данных от формата их передачи - сервер может поддерживать несколько различных форматов для передачи одних и тех же данных (JSON, XML и т.д.), но хранит данные в своем внутреннем формате, независимо от поддерживаемых.

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

    Чего нам не хватает

    Классический REST подразумевает работу клиента с сервером как с плоским хранилищем данных, при этом ничего не говорится о связанности и взаимозависимости данных между собой. Все это по умолчанию целиком ложится на плечи клиентского приложения. Однако современные предметные области, для которых разрабатываются системы управления данными, будь то социальные сервисы или системы интернет-маркетинга, подразумевают сложную взаимосвязь между сущностями, хранящимися в базе данных. Поддержка этих связей, т.е. целостности данных, находится в зоне ответственности серверной стороны, в то время, как клиент является только интерфейсом для доступа к этим данным. Так чего же нам не хватает в REST?

    Вызовы функций

    Чтобы не менять данные и связи между ними вручную, мы просто вызываем у ресурса функцию и «скармливаем» ей в качестве аргумента необходимые данные. Эта операция не подходит под стандарты REST, для нее не существует особого глагола, что заставляет нас, разработчиков, выкручиваться кто во что горазд.

    Самый простой пример – авторизация пользователя. Мы вызываем функцию login, передаем ей в качестве аргумента объект, содержащий учетные данные, и в ответ получаем ключ доступа. Что творится с данными на серверной стороне – нас не волнует.

    Еще вариант – создание и разрыв связей между данными. Например, добавление пользователя в группу. Вызываем у сущности группа функцию addUser, в качестве параметра передаем объект пользователь , получаем результат.

    А еще бывают операции, которые вообще не связаны напрямую с сохранением данных как таковых, например, рассылка уведомлений, подтверждение или отклонение каких-либо операций (завершение отчетного периода etc).

    Множественные операции

    Часто бывает так, и разработчики клиентов поймут, о чем я, что клиентскому приложению удобнее создавать/изменять/удалять/ сразу несколько однородных объектов одним запросом, и по каждому объекту возможен свой вердикт серверной стороны. Тут есть как минимум несколько вариантов: либо все изменения выполнены, либо они выполнены частично (для части объектов), либо произошла ошибка. Ну и стратегий тоже несколько: применять изменения только в случае успеха для всех, либо применять частично, либо откатываться в случае любой ошибки, а это уже тянет на полноценный механизм транзакций.

    Для web API, стремящегося к идеалу, тоже хотелось бы как-то привести подобные операции в систему. Постараюсь сделать это в одном из продолжений.

    Статистические запросы, агрегаторы, форматирование данных

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

    Уверен, что это далеко не все, с чем можно столкнуться при разработке реальных приложений, и буду рад вашим дополнениям и коррективам.

    Разновидности данных

    Объекты

    Ключевым типом данных в общении между клиентом и сервером выступает объект. По сути, объект – это перечень свойств и соответствующих им значений. Мы можем отправить объект на сервер в запросе и получить в результат запроса в виде объекта. При этом объект не обязательно будет реальной сущностью, хранящейся в базе данных, по крайней мере, в том виде, в котором он отправлен или получен. Например, учетные данные для авторизации передаются в виде объекта, но не являются самостоятельной сущностью. Даже хранимые в БД объекты склонны обрастать дополнительными свойствами внутрисистемного характера, например, датами создания и редактирования, различными системными метками и флагами. Свойства объектов могут быть как собственными скалярными значениями, так и содержать связанные объекты и коллекции объектов , которые не являются частью объекта. Часть свойств объектов может быть редактируемой, часть системной, доступной только для чтения, а часть может носить статистический характер и вычисляться на лету (например, количество лайков). Некоторые свойства объекта могут быть скрыты, в зависимости от прав пользователя.

    Коллекции объектов

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

    Скалярные значения

    В чистом виде скалярные значения как отдельная сущность на моей памяти встречались крайне редко. Обычно они фигурировали как свойства объектов или коллекций, и в этом качестве они могут быть доступны как для чтения, так и для записи. Например, имя пользователя может быть получено и изменено в индивидуальном порядке GET /users/1/name . На практике эта возможность пригождается редко, но в случае необходимости хотелось бы, чтобы она была под рукой. Особенно это касается свойств коллекции, например числа записей (с фильтрацией или без нее): GET /news/count .

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

    Приближение второе: Правильный путь

    В этом приближении я хотел бы отдельно поговорить о подходах к построению уникальных путей к ресурсам и методам вашего web API и о тех архитектурных особенностях приложения, которые влияют на внешний вид этого пути и его компоненты.

    О чем стоит подумать, стоя на берегу

    Версионность

    Рано или поздно любая действующая система начинает эволюционировать: развиваться, усложняться, масштабироваться, усовремениваться. Для разработчиков REST API это чревато в первую очередь тем, что необходимо запускать новые версии API при работающих старых. Здесь я говорю больше не об архитектурных изменениях под капотом вашей системы, а о том, что изменяется сам формат данных и набор операций с ними. В любом случае версионность нужно предусмотреть как в изначальной организации исходного кода, так и в принципе построения URL. Что касается URL, здесь существует два наиболее популярных способа указания версии API, которой адресован запрос. Префиксация пути example-api.com/v1/ и разведение версий на уровне субдомена v1.example-api.com . Использовать можно любой из них, в зависимости от потребности и необходимости.

    Автономность компонентов

    Web API сложных систем, поддерживающих несколько пользовательских ролей, зачастую требует разделения на части, каждая из которых обслуживает свой спектр задач. По сути, каждая часть может быть самостоятельным приложением, работать на разных физических машинах и платформах. В контексте описания API нам совершенно не важно, как сервер обрабатывает запрос и какие силы и технологии в этом замешаны. Для клиента API – система инкапсулированная. Тем не менее разные части системы могут обладать совершенно разной функциональностью, например, административная и пользовательская часть. И методология работы с одними и теми же, казалось бы, ресурсами может существенно отличаться. Поэтому такие части необходимо разделять на уровне домена admin.v1.example-api.com или префикса пути example-api.com/v1/admin/ . Это требование не является обязательным, и многое зависит от сложности системы и её назначения.

    Формат обмена данными

    Самым удобным и функциональным, на мой взгляд, форматом обмена данными является JSON, но никто не запрещает использовать XML, YAML или любой другой формат, позволяющий хранить сериализованные объекты без потери типа данных. При желании можно сделать в API поддержку нескольких форматов ввода/вывода. Достаточно задействовать HTTP заголовок запроса для указания желаемого формата ответа Accept и Content-Type для указания формата переданных в запросе данных. Другим популярным способом является добавление расширения к URL ресурса, например, GET /users.xml , но такой способ кажется менее гибким и красивым, хотя бы потому, что утяжеляет URL и верен скорее для GET-запросов, нежели для всех возможных операций.

    Локализация и многоязычность

    На практике многоязычность API чаще всего сводится к переводу сервисных сообщений и сообщений об ошибках на требуемый язык для прямого отображения конечному пользователю. Многоязычный контент тоже имеет место быть, но сохранение и выдача контента на разных языках, на мой взгляд, должна разграничиваться более явно, например, если у вас одна и та же статья существует на разных языках, то по факту это две разных сущности, сгруппированные по признаку единства содержания. Для идентификации ожидаемого языка можно использовать разные способы. Самым простым можно считать стандартный HTTP-заголовок Accept-Language . Я встречал и другие способы, такие, как добавление GET-параметра language="en" , использование префикса пути example-api.com/en/ или даже на уровне доменного имени en.example-api.com . Мне кажется, что выбор способа указания локали зависит от конкретного приложения и задач, стоящих перед ним.

    Внутренняя маршрутизация

    Итак, мы добрались до корневого узла нашего API (или одного из его компонентов). Все дальнейшие маршруты будут проходить уже непосредственно внутри вашего серверного приложения, в соответствии с поддерживаемым им набором ресурсов.

    Пути к коллекциям

    Для указания пути к коллекции мы просто используем название соответствующей сущности, например, если это список пользователей, то путь будет таким /users . К коллекции как таковой применимы два метода: GET (получение лимитированного списка сущностей) и POST (создание нового элемента). В запросах на получение списков мы можем использовать множество дополнительных GET параметров, применяемых для постраничного вывода, сортировки, фильтрации, поиска etc, но они должны быть опциональными, т.е. эти параметры не должны передаваться как часть пути!

    Элементы коллекции

    Для обращения к конкретному элементу коллекции мы используем в маршруте его уникальный идентификатор /users/25 . Это и есть уникальный путь к нему. Для работы с объектом применимы методы GET (получение объекта), PUT/PATCH (изменение) и DELETE (удаление).

    Уникальные объекты

    Во множестве сервисов существуют уникальные для текущего пользователя объекты, например профиль текущего пользователя /profile , или персональные настройки /settings . Разумеется, с одной стороны, это элементы одной из коллекций, но они являются отправной точкой в использовании нашего Web API клиентским приложением, и к тому же позволяют намного более широкий спектр операций над данными. При этом коллекция, хранящая пользовательские настройки может быть вообще недоступна из соображений безопасности и конфиденциальности данных.

    Свойства объектов и коллекций

    Для того, чтобы добраться до любого из свойств объекта напрямую, достаточно добавить к пути до объекта имя свойства, например получить имя пользователя /users/25/name . К свойству применимы методы GET (получение значения) и PUT/PATCH (изменение значения). Метод DELETE не применим, т.к. свойство является структурной частью объекта, как формализованной единицы данных.

    В предыдущей части мы говорили о том, что у коллекций, как и у объектов, могут быть собственные свойства. На моей памяти мне пригодилось только свойство count, но ваше приложение может быть более сложным и специфичным. Пути к свойствам коллекций строятся по тому же принципу, что и к свойствам их элементов: /users/count . Для свойств коллекций применим только метод GET (получение свойства), т.к. коллекция – это только интерфейс для доступа к списку.

    Коллекции связанных объектов

    Одной из разновидностей свойств объектов могут быть связанные объекты или коллекции связанных объектов. Такие сущности, как правило, не являются собственным свойством объекта, а лишь отсылками к его связям с другими сущностями. Например, перечень ролей, которые были присвоены пользователю /users/25/roles . По поводу работы с вложенными объектами и коллекциями мы подробно поговорим в одной из следующих частей, а на данном этапе нам достаточно того, что мы имеем возможность обращаться к ним напрямую, как к любому другому свойству объекта.

    Функции объектов и коллекций

    Для построения пути к интерфейсу вызова функции у коллекции или объекта мы используем тот же самый подход, что и для обращения к свойству. Например, для объекта /users/25/sendPasswordReminder или коллекции /users/disableUnconfirmed . Для вызовов функций мы в любом случае используем метод POST. Почему? Напомню, что в классическом REST не существует специального глагола для вызова функций, а потому нам придется использовать один из существующих. На мой взгляд, для этого больше всего подходит метод POST т.к. он позволяет передавать на сервер необходимые аргументы, не является идемпотентным (возвращающим один и тот же результат при многократном обращении) и наиболее абстрактен по семантике.

    Надеюсь, что все более-менее уложилось в систему 🙂 В следующей части мы поговорим подробнее о запросах и ответах, их форматах, кодах статусов.

    Приближение третье: Запросы и ответы

    В предыдущих приближениях я рассказал о том, как пришла идея собрать и обобщить имеющийся опыт разработки web API. В первой части я постарался описать, с какими видами ресурсов и операций над ними мы имеем дело при проектировании web API. Во второй части были затронуты вопросы построения уникальных URL для обращения к этим ресурсам. А в этом приближении я попробую описать возможные варианты запросов и ответов.

    Универсальный ответ

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

    Success - маркер успешности выполнения запроса

    Для того, чтобы при получении ответа от сервера сразу понять, увенчался ли запрос успехом, и передать его соответствующему обработчику, достаточно использовать маркер успешности «success». Самый простой ответ сервера, не содержащий никаких данных, будет выглядеть так:

    POST /api/v1/articles/22/publish { "success": true }

    Error - сведения об ошибке

    В случае, если выполнение запроса завершилось неудачей - о причинах и разновидностях отрицательных ответов сервера поговорим чуть позже, - к ответу добавляется атрибут «error», содержащий в себе HTTP-код статуса и текст сообщения об ошибке. Прошу не путать с сообщениями об ошибках валидации данных для конкретных полей. Правильнее всего, на мой взгляд, возвращать код статуса и в заголовке ответа, но я встречал и другой подход - в заголовке всегда возвращать статус 200 (успех), а детали и возможные данные об ошибках передавать в теле ответа.

    GET /api/v1/user { "success": false, "error": { "code" : 401, "message" : "Authorization failed" } }

    Data - данные, возвращаемые сервером

    Большинство ответов сервера призваны возвращать данные. В зависимости от типа запроса и его успеха ожидаемый набор данных будет разным, тем не менее атрибут«data» будет присутствовать в подавляющем большинстве ответов.

    Пример возвращаемых данных в случае успеха. В данном случае ответ содержит запрашиваемый объект user.

    GET /api/v1/user { "success": true, "data": { "id" : 125, "email" : "[email protected]", "name" : "John", "surname" : "Smith", } }

    Пример возвращаемых данных в случае ошибки. В данном случае содержит имена полей и сообщения об ошибках валидации.

    PUT /api/v1/user { "success": false, "error": { "code" : 422, "message" : "Validation failed" } "data": { "email" : "Email could not be blank.", } }

    Pagination - сведения, необходимые для организации постраничной навигации

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

    Минимальный набор значений для пагинации состоит из:

    • общего числа записей;
    • числа страниц;
    • номера текущей страницы;
    • числа записей на странице;
    • максимального числа записей на странице, поддерживаемого серверной стороной.

    Некоторые разработчики web API также включают в пагинацию набор готовых ссылок на соседние страницы, а также первую, последнюю и текущую.

    GET /api/v1/articles Response: { "success": true, "data": [ { "id" : 1, "title" : "Interesting thing", }, { "id" : 2, "title" : "Boring text", } ], "pagination": { "totalRecords" : 2, "totalPages" : 1, "currentPage" : 1, "perPage" : 20, "maxPerPage" : 100, } }

    Работа над ошибками

    Как уже упоминалось выше, не все запросы к web API завершаются успехом, но это тоже часть игры. Система информирования об ошибках является мощным инструментом, облегчающим работу клиента и направляющим клиентское приложение по правильному пути. Слово «ошибка» в этом контексте не совсем уместно. Здесь больше подойдёт слово исключение , так как на самом деле запрос успешно получен, проанализирован, и на него возвращается адекватный ответ, объясняющий, почему запрос не может быть выполнен.

    Каковы же потенциальные причины получаемых исключений?

    500 Internal server error - всё сломалось, но мы скоро починим

    Это как раз тот случай, когда проблема произошла на стороне самого сервера, и клиентскому приложению остаётся только вздохнуть и уведомить пользователя о том, что сервер устал и прилёг отдохнуть. Например, утеряно соединение с базой данных или в коде завелся баг.

    400 Bad request - а теперь у вас всё сломалось

    Ответ прямо противоположный предыдущему. Возвращается в тех случаях, когда клиентское приложение отправляет запрос, который в принципе не может быть корректно обработан, не содержит обязательных параметров или имеет синтаксические ошибки. Обычно это лечится повторным прочтением документации к web API.

    401 Unauthorized - незнакомец, назови себя

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

    403 Forbidden - вам сюда нельзя

    Запрашиваемый ресурс существует, но у пользователя недостаточно прав на его просмотр или модификацию.

    404 Not found - по этому адресу никто не живёт

    Такой ответ возвращается, как правило, в трёх случаях: путь к ресурсу неверен (ошибочен), запрашиваемый ресурс был удалён и перестал существовать, права текущего пользователя не позволяют ему знать о существовании запрашиваемого ресурса. Например, пока просматривали список товаров, один из них внезапно вышел из моды и был удалён.

    405 Method not allowed - нельзя такое делать

    Эта разновидность исключения напрямую связана с использованным при запросе глаголом (GET, PUT, POST, DELETE), который, в свою очередь, свидетельствует о действии, которое мы пытаемся совершить с ресурсом. Если запрошенный ресурс не поддерживает указанное действие, сервер говорит об этом прямо.

    422 Unprocessable entity - исправьте и пришлите снова

    Одно из самых полезных исключений. Возвращается каждый раз, когда в данных запроса существуют логические ошибки. Под данными запроса мы подразумеваем либо набор параметров и соответствующих им значений, переданных методом GET, либо поля объекта, передаваемого в теле запроса методами POST, PUT и DELETE. Если данные не прошли валидацию, сервер в секции «data» возвращает отчет о том, какие именно параметры невалидны и почему.

    Протокол HTTP поддерживает намного большее число различных статус-кодов на все случаи жизни, но на практике они используются редко и в контексте web API не несут практической пользы. На моей памяти мне не приходилось выходить за пределы вышеперечисленного списка исключений.

    Запросы

    Получение элементов коллекции

    Одним из наиболее частотных запросов является запрос на получение элементов коллекции. Информационные ленты, списки товаров, различные информационные и статистические таблицы и многое другое клиентское приложение отображает посредством обращения к коллекционным ресурсам. Для осуществления этого запроса мы обращаемся к коллекции, используя метод GET и передавая в строке запроса дополнительные параметры. Как мы уже обозначили выше, в качестве ответа мы ожидаем получить массив однородных элементов коллекции и информацию, необходимую для пагинации - подгрузки продолжения списка или же конкретной его страницы. Содержимое выборки может быть особым способом ограничено и отсортировано с помощью передачи дополнительных параметров. О них и пойдёт речь далее.

    Постраничная навигация

    page - параметр указывает на то, какая страница должна быть отображена. Если этот параметр не передан, то отображается первая страница. Из первого же успешного ответа сервера будет ясно, сколько страниц имеет коллекция при текущих параметрах фильтрации. Если значение превышает максимальное число страниц, то разумнее всего вернуть ошибку 404 Not found .

    GET /api/v1/news?page=1

    perPage - указывает на желаемое число элементов на странице. Как правило, API имеет собственное значение по умолчанию, которое возвращает в качестве поля perPage в секции pagination, но в ряде случаев позволяет увеличивать это значение до разумных пределов, предоставив максимальное значение maxPerPage:

    GET /api/v1/news?perPage=100

    Сортировка результатов

    Зачастую результаты выборки требуется упорядочить по возрастанию или убыванию значений определенных полей, которые поддерживают сравнительную (для числовых полей) или алфавитную (для строковых полей) сортировку. Например, нам нужно упорядочить список пользователей по имени или товары по цене. Помимо этого мы можем задать направление сортировки от A до Я или в обратном направлении, причём разное для разных полей.

    sortBy - существует несколько подходов к передаче данных о сложной сортировке в GET параметрах. Здесь необходимо четко указать порядок сортировки и направление.

    В некоторых API это предлагается сделать в виде строки:

    GET /api/v1/products?sortBy=name.desc,price.asc

    В других вариантах предлагается использовать массив:

    GET /api/v1/products? sortBy=name& sortBy=desc& sortBy=price& sortBy=asc

    В целом оба варианта равносильны, так как передают одни и те же инструкции. На мой взгляд, вариант с массивом более универсален, но тут, как говорится, на вкус и цвет…

    Простая фильтрация по значению

    Для того, чтобы отфильтровать выборку по значению какого либо поля, в большинстве случаев достаточно передать в качестве фильтрующего параметра имя поля и требуемое значение. Например, мы хотим отфильтровать статьи по ID автора:

    GET /api/v1/articles?authorId=25

    Усложнённые варианты фильтрации

    Многие интерфейсы требуют более сложной системы фильтрации и поиска. Перечислю основные и наиболее часто встречаемые варианты фильтрации.

    Фильтрация по верхней и нижней границе с использованием операторов сравнения from (больше или равно), higher (больше), to (меньше или равно), lower (меньше). Применяется к полям, значения которых поддаются ранжированию.

    GET /api/v1/products?price=500&price=1000

    Фильтрация по нескольким возможным значениям из списка. Применяется к полям, набор возможных значений которых ограничен, например, фильтр по нескольким статусам:

    GET /api/v1/products?status=1&status=2

    Фильтрация по частичному совпадению строки. Применяется к полям, содержащим текстовые данные или данные, которые могут быть приравнены к текстовым, например, числовые артикулы товаров, номера телефонов и т. д.

    GET /api/v1/users?name=John GET /api/v1/products?code=123

    Именованные фильтры

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

    GET /api/v1/products?filters=recommended

    Именованные фильтры могут также иметь свои параметры.

    GET /api/v1/products?filters=kidds

    В этом подразделе я постарался рассказать о наиболее популярных вариантах и способах получения требуемой выборки. Скорее всего, в вашей практике наберется намного больше примеров и нюансов касаемо этой темы. Если у вас есть, чем дополнить мой материал, я буду только рад. Тем временем пост уже разросся до солидных масштабов, так что другие виды запросов мы разберём в следующем приближении.

    Похожие публикации