Здесь показаны различия между двумя версиями данной страницы.
| Следующая версия | Предыдущая версия | ||
|
php:psr:psr-7 [2023/09/30 18:06] werwolf создано |
php:psr:psr-7 [2023/09/30 18:11] (текущий) werwolf |
||
|---|---|---|---|
| Строка 1: | Строка 1: | ||
| - | =====PSR-7===== | + | ===== 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-запроса имеет определенную форму: | ||
| + | |||
| + | <code bash> | ||
| + | POST /path HTTP/1.1 | ||
| + | Host: example.com | ||
| + | |||
| + | foo=bar&baz=bat | ||
| + | </code> | ||
| + | |||
| + | Первая строка запроса является "строкой запроса" и содержит по порядку метод HTTP-запроса, целевой объект запроса (обычно либо абсолютный URI, либо путь на веб-сервере) и версию протокола HTTP. Далее следует один или несколько заголовков HTTP, пустая строка и текст сообщения. | ||
| + | |||
| + | Ответные сообщения HTTP имеют схожую структуру: | ||
| + | |||
| + | <code bash> | ||
| + | HTTP/1.1 200 OK | ||
| + | Content-Type: text/plain | ||
| + | |||
| + | This is the response body | ||
| + | </code> | ||
| + | |||
| + | Первая строка является "строкой состояния" и содержит по порядку версию протокола 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''. | ||
| + | |||
| + | <code php> | ||
| + | $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 | ||
| + | </code> | ||
| + | |||
| + | Несмотря на то, что заголовки могут быть получены без учета регистра, исходный регистр ДОЛЖЕН быть сохранен реализацией, в частности, при получении с помощью ''getHeaders()''. | ||
| + | |||
| + | Несоответствующие HTTP-приложения могут зависеть от определенного случая, поэтому пользователю полезно иметь возможность диктовать регистр HTTP-заголовков при создании запроса или ответа. | ||
| + | |||
| + | [[#заголовки-с-несколькими-значениями|Заголовки с несколькими значениями]] | ||
| + | |||
| + | Чтобы разместить заголовки с несколькими значениями, но при этом обеспечить удобство работы с заголовками в виде строк, заголовки могут быть извлечены из экземпляра ''MessageInterface'' в виде массива или строки. Используйте метод ''getHeaderLine()'' для получения значения заголовка в виде строки, содержащей все значения заголовка без учета регистра имени, перечисленныые через запятую. Используйте ''getHeader()'', чтобы по имени заголовка, получить массив всех значений конкретного заголовка нечувствительного к регистру. | ||
| + | |||
| + | <code php> | ||
| + | $message = $message | ||
| + | ->withHeader('foo', 'bar') | ||
| + | ->withAddedHeader('foo', 'baz'); | ||
| + | |||
| + | $header = $message->getHeaderLine('foo'); | ||
| + | // $header содержит: 'bar,baz' | ||
| + | |||
| + | $header = $message->getHeader('foo'); | ||
| + | // ['bar', 'baz'] | ||
| + | </code> | ||
| + | |||
| + | Примечание: не все значения заголовка могут быть объединены с помощью запятой (например, ''Set-Cookie''). При работе с такими заголовками потребители классов основанных на ''MessageInterface'' ДОЛЖНЫ полагаться на метод ''getHeader()'' для извлечения таких многозначных заголовков. | ||
| + | |||
| + | [[#заголовок-host|Заголовок Host]] | ||
| + | |||
| + | В запросах, заголовок ''Host'', обычно отражает хостовую часть от URI, а также хост, используемый при установлении TCP-соединения. Однако, спецификация HTTP для каждого из них позволяет заголовку ''Host'' отличаться. | ||
| + | |||
| + | Если заголовок ''Host'' не установлен, то во время создания, реализация ДОЛЖНА попытаться установить заголовок ''Host'' из предоставленного URI. | ||
| + | |||
| + | ''RequestInterface::withUri()'' по умолчанию заменит заголовок ''Host'' возвращаемого запроса, на заголовок c ''Host'' соответствующего части хоста переданного из ''UriInterface''. | ||