===== PSR-7: Интерфейс HTTP Сообщений ===== Этот документ описывает общие интерфейсы для представления HTTP сообщений, как описано в [[https://tools.ietf.org/html/rfc7230|RFC 7230]] и [[https://tools.ietf.org/html/rfc7231|RFC 7231]], и URI для использования с сообщениями HTTP, как описано в [[https://tools.ietf.org/html/rfc3986|RFC 3986]]. HTTP-сообщения являются основой веб-разработки. Веб-браузеры и HTTP-клиенты, такие как cURL, создают HTTP-запрос, который отправляется на веб-сервер, предоставляющий HTTP-ответ. Серверный код получает HTTP-запрос и возвращает ответное сообщение HTTP. Сообщения HTTP обычно абстрагируются от конечного потребителя, но как разработчики, мы как правило должны знать, как они структурированы и как получить доступ к ним или манипулировать ими для выполнения наших задач, будь то выполнение запроса к HTTP API или обработка входящего запроса. Каждое сообщение HTTP-запроса имеет определенную форму: POST /path HTTP/1.1 Host: example.com foo=bar&baz=bat Первая строка запроса является "строкой запроса" и содержит по порядку метод HTTP-запроса, целевой объект запроса (обычно либо абсолютный URI, либо путь на веб-сервере) и версию протокола HTTP. Далее следует один или несколько заголовков HTTP, пустая строка и текст сообщения. Ответные сообщения HTTP имеют схожую структуру: HTTP/1.1 200 OK Content-Type: text/plain This is the response body Первая строка является "строкой состояния" и содержит по порядку версию протокола HTTP, код состояния HTTP и "формулировка причины" - удобочитаемое описание кода состояния. Как и сообщение запроса, за ним следует один или несколько заголовков HTTP, пустая строка и тело сообщения. Интерфейсы, описанные в этом документе, являются абстракциями вокруг HTTP-сообщений и составляющих их элементов. Ключевые слова 'ДОЛЖНЫ', 'НЕ ДОЛЖНЫ', 'ТРЕБУЕТСЯ', 'НУЖНО', 'НЕ НУЖНО', 'СЛЕДУЕТ', 'НЕ СЛЕДУЕТ', 'РЕКОМЕНДУЕТСЯ', 'МОЖЕТ' и 'НЕОБЯЗАТЕЛЬНО' в этом документе должны толковаться так, как описано в [[:MiklyxoMaklai:rus-PSR:blob:master:rfc2119|RFC 2119]]. [[#ссылки|Ссылки]] * [[https://tools.ietf.org/html/rfc2119|RFC 2119]] * [[https://tools.ietf.org/html/rfc3986|RFC 3986]] * [[https://tools.ietf.org/html/rfc7230|RFC 7230]] * [[https://tools.ietf.org/html/rfc7231|RFC 7231]] === 1. Описание === == 1.1 Сообщения == HTTP-сообщение - это либо запрос от клиента к серверу, либо ответ от сервера клиенту. Это описание определяет интерфейсы для сообщений HTTP ''Psr\Http\Message\RequestInterface'' и ''Psr\Http\Message\ResponseInterface'' соответственно. Оба интерфейса ''Psr\Http\Message\RequestInterface'' и ''Psr\Http\Message\ResponseInterface'' расширяют ''Psr\Http\Message\MessageInterface''. В то время как интерфейс ''Psr\Http\Message\MessageInterface'' МОЖЕТ быть реализован напрямую, разработчики ДОЛЖНЫ реализовать интерфейсы ''Psr\Http\Message\RequestInterface'' и ''Psr\Http\Message\ResponseInterface''. В дальнейшем пространство имен ''Psr\Http\Message'' будет опущено при обращении к этим интерфейсам. == 1.2 HTTP-Заголовки == [[#имена-полей-заголовка-без-учета-регистра|Имена полей заголовка без учета регистра]] HTTP-сообщения содержат имена полей заголовка без учета регистра. Заголовки извлекаются по имени из классов, реализующих интерфейс ''MessageInterface'' без учета регистра. Например, извлечение заголовка ''foo'' вернет тот же результат, что и извлечение заголовка ''FoO''. Аналогично, установка заголовка ''Foo'' перезапишет любое ранее установленное значение заголовка в ''foo''. $message = $message->withHeader('foo', 'bar'); echo $message->getHeaderLine('foo'); // Выведет: bar echo $message->getHeaderLine('FOO'); // Выведет: bar $message = $message->withHeader('fOO', 'baz'); echo $message->getHeaderLine('foo'); // Выведет: baz Несмотря на то, что заголовки могут быть получены без учета регистра, исходный регистр ДОЛЖЕН быть сохранен реализацией, в частности, при получении с помощью ''getHeaders()''. Несоответствующие HTTP-приложения могут зависеть от определенного случая, поэтому пользователю полезно иметь возможность диктовать регистр HTTP-заголовков при создании запроса или ответа. [[#заголовки-с-несколькими-значениями|Заголовки с несколькими значениями]] Чтобы разместить заголовки с несколькими значениями, но при этом обеспечить удобство работы с заголовками в виде строк, заголовки могут быть извлечены из экземпляра ''MessageInterface'' в виде массива или строки. Используйте метод ''getHeaderLine()'' для получения значения заголовка в виде строки, содержащей все значения заголовка без учета регистра имени, перечисленныые через запятую. Используйте ''getHeader()'', чтобы по имени заголовка, получить массив всех значений конкретного заголовка нечувствительного к регистру. $message = $message ->withHeader('foo', 'bar') ->withAddedHeader('foo', 'baz'); $header = $message->getHeaderLine('foo'); // $header содержит: 'bar,baz' $header = $message->getHeader('foo'); // ['bar', 'baz'] Примечание: не все значения заголовка могут быть объединены с помощью запятой (например, ''Set-Cookie''). При работе с такими заголовками потребители классов основанных на ''MessageInterface'' ДОЛЖНЫ полагаться на метод ''getHeader()'' для извлечения таких многозначных заголовков. [[#заголовок-host|Заголовок Host]] В запросах, заголовок ''Host'', обычно отражает хостовую часть от URI, а также хост, используемый при установлении TCP-соединения. Однако, спецификация HTTP для каждого из них позволяет заголовку ''Host'' отличаться. Если заголовок ''Host'' не установлен, то во время создания, реализация ДОЛЖНА попытаться установить заголовок ''Host'' из предоставленного URI. ''RequestInterface::withUri()'' по умолчанию заменит заголовок ''Host'' возвращаемого запроса, на заголовок c ''Host'' соответствующего части хоста переданного из ''UriInterface''.