Реквест респонс что это
Request response diagram: что такое и зачем это нужно
Мы продолжаем серию публикаций об артефактах, которые клиенты получают на самой первом этапе разработки — дискавери фазы. Мы уже объяснили, что такое MindMap, Пользовательские истории, BPMN-диаграмма, Customer Journey Map и как мы используем эти инструменты в разработке. Сегодня говорим о Request response diagram — этот артефакт необязательный, мы его используем, если в проекте предусмотрены интеграции (например, с Google-переводчиком, сервисом доставки и логистики, онлайн-оплатой и т. д.).
Request response diagram или диаграмма последовательности — разновидность диаграмм взаимодействия. Обычно она содержит объекты, которые взаимодействуют в рамках сценария, сообщения, которыми они обмениваются, и возвращаемые результаты, связанные с сообщениями. Диаграммы последовательностей используются для более детального описания логики сценариев использования.
Request response diagram отражает:
В отличие от BPMN-диаграммы, которая показывает алгоритм работы системы, Request response diagram обращают внимание разработчиков на сообщениях, которыми объекты обмениваются друг с другом.
Разберем на простом примере, как работает Request response diagram, чтобы наглядно представить, как работает этот артефакт. Эта диаграмма отображает обслуживание в ресторане:
Фред (клиент) заказывает еду Бобу (официанту), Боб передает заказ Хэнку (повару). Пока повар готовит еду, официант наливает вино клиенту. Хэнк отдает заказ Бобу, Боб сервирует блюда. Фред ест и потом рассчитывается за ужин через кассира Ренне.
Это простая схема, в веб и мобильной разработке на таких диаграммах отображаются более сложные процессы и интеграции. Но такой инструмент дает понимание логики процесса, так как мы видим как должны работать объекты на протяжении всего временного цикла. Request response diagram — довольно сложная нотация, которая имеет свой язык. Чтобы правильно прочитать ее, необходимо знать значение каждого символа. Останавливаться на расшифровке мы сейчас не будем, так как клиентам студии обычно не приходится разбираться с диаграммой, этот артефакт скорее оптимизирует работу в команде разработчиков.
Request response diagram чаще всего применяются на этапе дискавери фазы, когда у сервиса есть интеграция.
Есть интеграция — есть необходимость прописать логику с этой интеграцией.Эта логика заключается не только в том, чтобы показать запросы и ответы самой системы, но и в экономии средств клиента, в случае если интеграция платная.
Бизнес или системные аналитики в компании с проджект-менеджером разрабатывают бизнес-модель, которая позволит сделать продуктивную и экономичную интеграцию. На примере интеграции с google-переводчиком (на схеме ниже) видно, что эта диаграмма показывает, как сохранить все переведенные ранее тексты в систему, чтобы пользоваться ими в будущем. Тем самым не придется каждый раз обращаться к платному переводчику и тратить деньги клиента.
После дискавери фазы, имея на руках проработанную интеграцию, разработчик понимает, каким образом она должна работать. В этом случае он может дать оценку по времени и соответственно стоимости разработки. Приступая к работе, разработчик тратит гораздо меньше времени, чтобы реализовать интеграцию. Клиент получает результат интеграции с системой в более короткий срок.
Поэтому мы всегда рекомендуем делать диаграмму на этапе дискавери (но только тогда, когда это действительно нужно проекту). Однако решение всегда остается за заказчиком.
Выбор Request-Response парадигмы API: REST, RPC или GraphQL?
Авторизуйтесь
Выбор Request-Response парадигмы API: REST, RPC или GraphQL?
API определяет интерфейс, предоставляющий данные сервиса другим приложениям. Выбор правильного формата API крайне важен. Бизнес не всегда учитывает все факторы, выбирая формат. В результате не хватает возможности для добавления новых фич, которые могут понадобиться в дальнейшем.
Чтобы сэкономить время, силы, а самое главное деньги, стоит посмотреть на best practices, которые применяются на текущий момент. Это поможет разработать API, который позволит вносить необходимые изменения в будущем. За прошедшие годы появилось несколько форматов API, рассмотрим самые популярные из них.
Request-Response APIs
Первую группу API, которую мы рассмотрим, можно выделить как Request-Response API. Основные отличия данной группы:
Самые популярные request-response API: REST, RPC и GraphQL.
Самый популярный подход на данный момент. Используется такими поставщиками API, как, например, Google, Twitter и GitHub.
Когда мы говорим про REST, мы говорим про ресурсы. Ресурс — это объект, который может быть идентифицирован, назван, адресован или обработан в сети. REST представляет данные как ресурсы и использует стандартные HTTP-методы для представления транзакций создания, чтения, обновления и удаления этих ресурсов, то есть стандартные CRUD операции. По сути, все бизнес-сущности, которыми оперирует сервис, могут быть определены как ресурсы.
Общие правила, которым следует RESTful API:
Помимо типичных операций CRUD, API-интерфейсы REST могут иногда нуждаться в представлении операций, не относящихся к CRUD. В этом случае обычно используются следующие подходы:
Для API, предоставляющего CRUD-операции.
Remote Procedure Call (RPC)
Удаленный вызов процедур (RPC) — это одна из простейших парадигм API, в которой клиент вызывает исполнение блока кода на сервере. В то время как REST рассматривает всё как ресурсы, RPC рассматривает действия. Клиенты обычно передают имя метода и аргументы серверу и получают обратно JSON или XML.
Для API, предоставляющего действия, которые сложно инкапсулировать в CRUD операциях.
GraphQL
GraphQL — это язык запросов для API, который в последнее время приобрел значительную популярность. Он был разработан внутри Facebook в 2012 году до публичного выпуска в 2015 году. GraphQL позволяет клиентам определять структуру требуемых данных. Сервер возвращает именно эту структуру
В отличие от REST и RPC API, GraphQL требует только один эндпоинт URL. Также вам не нужны разные HTTP-методы для описания операции. Вместо этого вы указываете в теле JSON выполняете ли вы запрос или мутацию. GraphQL поддерживает методы GET и POST.
Плюсы:
Минусы:
Объекты запроса и ответа (Request & Response Objects)
Содержание
Объекты запроса и ответа (Request & Response Objects) являются абстрактными представителями HTTP-запросов и ответов. Объект запроса в CakePHP позволяет работать с входящим запросом, в то время как объект ответа позволяет легко создавать ответы HTTP от контроллеров приложения.
Запрос (Request)
class Cake\Http\ServerRequest
Начиная с версии 3.4.0, объект запроса CakePHP реализует PSR-7 ServerRequestInterface, что упрощает использование библиотек вне CakePHP.
Параметры запроса
Параметры маршрутизации из объекта запроса можно получить используя метод getParam():
Через этот интерфейс доступны все элементы маршрута.
Помимо Route Elements (элементов маршрута),также часто необходим доступ к Passed Arguments (передаваемым аргументам). Они также доступны в объекте запроса:
Всё это предоставят доступ к переданным аргументам. Существует несколько важных/полезных параметров, которые CakePHP использует внутренне, все они также находятся в параметрах маршрутизации:
Параметры строки запроса
Cake\Http\ServerRequest::getQuery($name)
Параметры строки запроса можно прочитать с помощью метода getQuery():
Вы можете либо напрямую получить доступ к свойству запроса, указав имя свойства, либо использовать метод getQuery() без указания имени (ключа) для чтения всего массива запроса. Любые ключи, которые не существуют, будут приводить к возвращению значения null:
Так же, для получения доступа ко всем параметрам запроса, можно использовать getQueryParams ():
Новое в версии 3.4.0: getQueryParams() и getQuery() добавлены в 3.4.0
Данные тела запроса
Доступ ко всем данным POST можно получить с помощью Cake\Http\ServerRequest::getData(). Любые данные, отправленные из формы, содержащие многомерный массив, будут иметь префикс данных. Например:
Любые ключи, которые не существуют, будут возвращать значение null:
Данные методов PUT, PATCH или DELETE в запросе
При создании REST сервиса часто бывает необходимо принимать в запросе данные PUT и DELETE. Любые application/x-www-form-urlencoded данные тела запроса автоматически анализируются, парсятся и заносятся в $this->data для запросов PUT и DELETE. Если вы принимаете данные JSON или XML, то ниже показано, как можно получить доступ к телам этих запросов.
Для доступа к входным данным вы можете декодировать их с помощью дополнительной функции. Это полезно при взаимодействии с содержимым тела запроса XML или JSON. Дополнительные параметры для функции декодирования могут передаваться в качестве аргументов для input():
Чтобы получить доступ ко всем переменным среды в запросе, используется getServerParams():
Новое в версии 3.4.0: Метод getServerParams() добавлен в 3.4.0
XML или JSON данные
Приложения, использующие REST, часто обмениваются данными без URL-кодирования. Прочитать входные данные любого формата, можно используя Http\\ServerRequest::input(). Указывая функцию декодирования, вы можете получать контент в десериализованном формате:
Некоторые методы десериализации требуют дополнительных параметров при вызове, таких как параметр «ассоциативный массив» при использовании json_decode. Если вы хотите преобразовать XML в объект DOMDocument, Http\ServerRequest::input() поддерживает передачу дополнительных параметров:
Информация о пути (Path)
Объект запроса также предоставляет информацию о путях в вашем приложении. Атрибуты base и webroot полезны для создания URL-адресов и определения того, находится ли ваше приложение в подкаталоге. Возможно использование следующих атрибутов:
Проверка условий запроса
Объект запроса обеспечивает простой способ проверки определенных условий в запросе. Используя метод is(), можно проверить ряд общих условий, а также другие критерии запроса конкретного приложения:
Так же, можно расширить условия проверки запросов, используя Cake\Http\ServerRequest::addDetector() для создания новых типов детекторов. Существует четыре разных типа детекторов, которые могут быть созданы:
Вот некоторые примеры:
Request также включает в себя такие методы, как: Cake\Http\ServerRequest::domain(), Cake\Http\ServerRequest::subdomains() и Cake\Http\ServerRequest::host(), чтобы помочь облегчить жизнь при создании приложений с субдоменами.
Существует несколько встроенных детекторов, которые вы можете использовать:
Новое в версии 3.3.0: Детекторы могут принимать дополнительные параметры начиная с версии 3.3.0
Данные сессии (Session Data)
Для доступа к сессии текущего запроса используется метод session():
Хост и доменное имя
Cake\Http\ServerRequest::domain($tldLength = 1)
Возвращает имя домена, в котором работает ваше приложение:
Cake\Http\ServerRequest::subdomains($tldLength = 1)
Возвращает субдомены, в которых работает ваше приложение, в виде массива:
Cake\Http\ServerRequest::host()
Возвращает хост, на котором установлено ваше приложение:
Чтение HTTP-метода
Cake\Http\ServerRequest::getMethod()
Возвращает метод HTTP, на основе которого был выполнен запрос:
Ограничение того, какой метод HTTP может принимать экшен
Cake\Http\ServerRequest::allowMethod($methods)
После установки допустимых методов HTTP, если они не будут согласованы с запросом, выбросится исключение MethodNotAllowedException. Ответ 405 будет включать заголовок с указанием разрешенных методов:
Чтение заголовков HTTP
Позволяет получить доступ к любому из заголовков HTTP_ *, которые были использованы для запроса. Например:
Хотя некоторые установки Apache делают заголовок при авторизации не доступным, CakePHP сделает его доступным по специальным методам apache в случае необходимости.
Cake\Http\ServerRequest::referer($local = false)
Возвращает URL адрес источника запроса.
Cake\Http\ServerRequest::clientIp()
Возвращает IP-адрес текущего посетителя.
Заголовки доверенного прокси
Если ваше приложение находится за балансировщиком нагрузки или работает в облачном сервисе, часто бывает необходимо получать от них хост, порт и схему в своих запросах. Такие балансировки нагрузки также отправляют заголовки HTTP-X-Forwarded- * с исходными значениями. Пересылаемые заголовки не будут использоваться CakePHP из коробки. Чтобы объект запроса использовал эти заголовки, для свойства trustProxy необходимо установить значение true:
Проверка принимающих заголовков
Cake\Http\ServerRequest::accepts($type = null)
Можно узнать, какие типы данных (Content-Type) принимает клиент, или проверьте, принимает ли он конкретный Content-Type.
Проверка конкретного типа:
Cake\Http\ServerRequest::acceptLanguage($language = null)
Получить все языки, принятые клиентом, или проверить, принят ли конкретный язык.
Получить список принятых языков::
Проверьте, принят ли конкретный язык::
Cookie (куки)
Куки запроса можно прочитать несколькими способами:
См. документацию по Cake\Http\Cookie\CookieCollection для работы с экземпляром коллекции файлов куки.
Новое в версии 3.5.0: ServerRequest::getCookieCollection() добавлен в версии 3.5.0
Ответ (Response)
class Cake\Http\Response
Response предоставляет интерфейс для объединения задач, связанных с ответом, таких как:
Работа с типами контента
Cake\Http\Response::withType($contentType = null)
Вы можете управлять Content-Type в ответах приложения с помощью Cake\Http\Response::withType(). Если приложению нужно иметь дело с Content-Types, которые не встроены в Response, их можно также сопоставить с type():
Обычно необходимо отображать дополнительные Content-Type в обратном вызове beforeFilter() контроллера, для этого можно использовать функции автоматического переключения вида RequestHandlerComponent, при его использовании.
Отправка файлов
Бывают случаи, когда необходимо отправлять файлы в качестве ответов на запросы. Это можно делать, используя Cake\Http\Response::withFile():
Как показано в приведённом выше примере, необходимо в метод передать путь к файлу. CakePHP отправит соответствующий заголовок типа контента, если это известный тип файла, указанный в Cake\Http\Reponse::$_mimeTypes. Вы можете добавлять новые типы до вызова Cake\Http\Response::withFile() с помощью метода Cake\Http\Response::withType().
Также можно принудительно загрузить файл вместо отображения страницы в браузере, указав параметры:
Отправка строки в виде файла
Так же, можно ответить файлом, который не существует на диске, например, pdf или ics, сгенерированным «на лету» из строки:
Обратные вызовы также могут возвращать тело в виде строки:
Настройка заголовков
Настройка заголовков выполняется с помощью метода Cake\Http\Response::withHeader(). Как и все методы интерфейса PSR-7, этот метод возвращает экземпляр new с новым заголовком:
Заголовки не отправляются при установке. Вместо этого они сохраняются до тех пор, пока не будет получен ответ Cake\Http\Server.
Теперь вы можете использовать удобный метод Cake\Http\Response::withLocation(), чтобы напрямую установить или получить заголовок местоположения перенаправления.
Настройка body
Cake\Http\Response::withStringBody($string)
Чтобы установить строку в качестве тела ответа, необходимо выполнить следующие действия:
request-response
Смотреть что такое «request-response» в других словарях:
Request-response — Request response, also known as request reply, is a message exchange pattern in which a requestor sends a request message to a replier system which receives and processes the request, ultimately returning a message in response. This is a simple,… … Wikipedia
request — [ri kwest′] n. [ME < OFr requeste < ML requesta < fem. pp. of VL * requaerere: see REQUIRE] 1. the act of asking, or expressing a desire, for something; solicitation or petition 2. something asked for [to grant a request] 3. the state of … English World dictionary
Request for evidence — (RFE), as pertinent to immigration processing, is a formal response from USCIS, issued when insufficient or suspicious data is found, typically in I 140 or I 485 petitions.RFE and petition processing is a fairly volatile area in the US… … Wikipedia
response time — UK US noun [C] ► a measure of the time it takes to react to something: »The emergency service response time has improved in the past three months. ► IT a measure of the time it takes a computer to react to a request to do something: »Response… … Financial and business terms
response — [n] answer, reaction acknowledgment, antiphon, back talk*, comeback, counter, double take*, echo, feedback, hit, kickback*, knee jerk reaction*, lip*, rejoinder, reply, respond, retort, return, reverberation, riposte, sass*, snappy comeback*,… … New thesaurus
Response time (technology) — In technology, response time is the time a system or functional unit takes to react to a given input. Data processing In data processing, the response time perceived by the end user is the interval between :(a) the instant at which an operator at … Wikipedia
request — requester, n. /ri kwest /, n. 1. the act of asking for something to be given or done, esp. as a favor or courtesy; solicitation or petition: At his request, they left. 2. an instance of this: There have been many requests for the product. 3. a… … Universalium
Request for production — Civil procedure in the United States Federal Rules of Civil Procedure Doctrines of civil procedure Jurisdiction Subject matter jurisdiction Diversity jurisdiction Personal jurisdiction Removal jurisdiction Venue Change of venue … Wikipedia
request — n. & v. n. 1 the act or an instance of asking for something; a petition (came at his request). 2 a thing asked for. 3 the state of being sought after; demand (in great request). 4 a letter etc. asking for a particular record etc. to be played on… … Useful english dictionary
Request Cycle — Der Request Cycle ist der Zyklus, der in einer Webanwendung abläuft. Auslöser für diesen Zyklus kann zum Beispiel sein, dass der Benutzer in seinem Browser einen Link klickt. Dann wird von seinem Browser ein HTTP Request generiert und zum Server… … Deutsch Wikipedia
Устройство фреймворка Symfony: от запроса до ответа
Немного истории
Во-первых, все ваши контроллеры обязаны содержать постфикс Controller, что немного неудобно. А во-вторых, ваши контроллеры не принимают зависимости и не могут работать с ними. А что, если вам понадобится какой-то сервис, работающий с API, а тот, в свою очередь, принимает http-клиент Guzzle? Не проблема, делаем так:
Request/Response


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

Строгость фреймворка обязывает вас из всех контроллеров возвращать инстанс класса Response. Это может быть не простой Response, а JsonResponse, если вы пишете апи, RedirectResponse, если вам нужно сделать редирект, BinaryFileResponse, если нужно вернуть файл, и многое другое.
А что посередине?
На самом деле, Request/Response – это простые классы, которые могут работать и без Symfony, в них самих ничего необычного нет. Интересно то, что находится между точками запрос и ответ.
В первую очередь, мы создаем экземпляр Kernel’а, передавая туда переменные окружения (в каком окружении находимся – dev или prod – и нужен ли нам дебаг), и вызываем метод handle, куда отправляем текущий Request. Метод handle загружает (boot) бандлы (о них чуть ниже) и инициализирует контейнер (о котором тоже чуть ниже):

Когда контейнер готов, Symfony достает из него HttpKernel и вызывает у него метод handle, куда передает текущий запрос, тип (MASTER_REQUEST соответствует основному запросу, который пришел от пользователя) и нужно ли ловить ошибку или нет: если нет, Symfony просто выплюнет ошибку вам на экран, если да, то сработают слушатели, подписавшиеся на событие kernel.exception (о слушателях так же ниже), и ответ вернется уже из одного из них.
Контейнер
Теперь настало время поговорить о том, что же такое контейнер и зачем он нужен. Если коротко, то контейнер – это объект, который знает, как создать конкретный класс и как настроить его зависимости. В случае простого MVC, который писал каждый разработчик, вам приходилось или руками инжектить все эти зависимости, или не использовать вовсе, отдавая предпочтение неуправляемым и жестким статическим методам класса. Контейнер же справляется с этой задачей, располагая в результате компиляции всей информацией о всех необходимых сервисах, которые когда-либо может запросить ваше приложение. Таким образом, когда Symfony уже знает, какой контроллер вам нужен, и если этот контроллер требует зависимости, фреймворк использует контейнер для автовайринга (автозагрузки) некоторых сервисов (например, если вы используете Connection, EntityManager или что-то еще). Если вы хотите подробнее почитать про контейнер и внедрение зависимостей, вы можете прочитать статью Мартина Фаулера о принципах внедрения зависимостей, о типах внедрения (через конструктор или сеттер), о контейнерах и многом другом.
Бандлы
Как написано в документации к фреймворку, бандлы – это что-то очень похожее на плагины. У бандлов достаточно широкая конфигурация, их можно включить в любом окружении или отключать вовсе, бандлы могут повлиять на компиляцию контейнера, а также добавляют больше информации о внедряемых сервисах. Объяснять, как писать бандлы, я не буду, эта тема для отдельной статьи.
Посредники
Вероятно, многие слышали про посредники (или middleware): это классы-фильтры, обрабатывающие http-запрос до того, как он попадет в контроллер. Посредники могут не пропустить запрос, если не прошла валидация или аутентификация, и тогда именно посредники возвращают ответ, а не контроллер. Если же все хорошо, один посредник передает запрос другому посреднику, и так по цепочке, пока запрос не попадет в контроллер. А теперь забудьте, что я написал, потому что в Symfony нет посредников, там в качестве оных могут выступать и выступают события. Существует как ряд встроенных событий, которыми обменивается фреймворк в процессе обработки запроса, так и кастомные события, которые вы сделаете сами. Вот список встроенных событий, на которые подписаны слушатели фреймворка и на которые могут подписаться ваши слушатели, чтобы как-то повлиять на работу фреймворка в любой момент:
В аннотациях к константам имен событий указаны сами классы событий, которые может принять ваш слушатель, когда на них подпишется. Например, вот так:
Таким образом, самое первое событие, которое кидает Symfony, – это событие KernelEvents::REQUEST:




Дальше бросается событие KernelEvents::CONTROLLER :

Сам ArgumentResolver выглядит так:

Здесь перебираются все зарегистрированные резолверы, собираются аргументы и возвращаются обратно. Вот для примера два важных резолвера — RequestValueResolver и ServiceValueResolver :


Последний резолвер ( ServiceValueResolver ) как раз и занимается тем, что достает аргументы контроллера из контейнера, если их не получилось достать другими резолверами.
Дальше собирается и вызывается контроллер:
Кроме этого, Symfony бросает оставшиеся 4 события:
Вы можете подписаться на любое из этих событий и по-прежнему повлиять на работу фреймворка. Например, вы можете подписаться на событие EXCEPTION, словить AccessDeniedException, который вы выкинете в любом из контроллеров, и отрендерить шаблон с ошибкой 403:
Или же вы можете переложить всю работу на аннотации, закрыть ею все защищенные маршруты и выкидывать исключение из слушателя, который будет смотреть, определена ли конкретная аннотация над ней или нет. Будет выглядеть это следующим образом:
Сервисы
После этого идем в файл config/services.yaml и начинаем описывать наш сервис. По умолчанию этот файл выглядит следующим образом:
Какая настройка и для чего нужна, я описывать не буду, комментарии напротив каждой из них достаточно подробные.
Предположим, вы написали клиент, который в конструктор принимает токен и GuzzleHttp для запросов к API. Для описания такого сервиса нам нужно определить имя сервиса (в новых версиях фреймворка имена соответствуют FQCN класса), его аргументы и вызываемые методы, если они есть:
В секции arguments список аргументов может быть как упорядоченным, так и параметризированным. Если вы не хотите зависеть от порядка передаваемых аргументов, вы можете их явно привязать к именам аргументов ваших классов. Например:
Давайте усложним задачу. Теперь у вас JWT авторизация, и перед совершением запросов к API необходимо получить access_token, и так постоянно. Однако вы не хотите зависеть от этого фактора в своем коде и не хотите рисковать забыть сделать запрос на получение токена перед запросом. Symfony может вам помочь. Для этого вам необходимо в секции calls перечислить методы, какие нужно вызвать перед тем, как фреймворк отдаст вам сервис:
Теперь при запросе своего клиента вы получите уже полностью сконфигурированный класс.
Вместо завершения
Как видите, Symfony достаточно удобный и легко расширяемый фреймворк. Кроме того, он состоит из компонентов, которые вы можете использовать отдельно от него. Например, самыми популярными из них являются компонент для создания консольных команд, роутинг, dependency injection и некоторые другие.
Если кому-либо понравилось читать про устройство Symfony, дополнительно могу написать про интересные приемы работы с фреймворком и личные (и немного общие) best practice.

