Относно методите, със get… вземаш, със with… променяш но първо клонираш.
Всичко в WWW се базира на клиент-сървър архитектурата и съответно – размяната на HTTP messages между тях – клиентът и сървът.
Относно натрапчивият въпрос, ОК какво разбираме под Request, или по-скоро – от коя страна да го гледаме? Tова, което клиентът изпраща, още от негова страна? Или това, което сървът е приел от негова страна?
Съдейки по този цитат:
Web browsers and HTTP clients such as cURL create HTTP request messages that are sent to a web server, which provides an HTTP response message.
Излиза, че е едно и също, и Рекуестът, и Респонсът, независимо от коя страна го гледаме. Нали все пак това, което изпраща клиентът е това, което получава сървът? Какво друго да е?
Прехвърлянето не променя нищо.
Рекуестът е рекуест и за рекуестващият, и за рекуестнатият, един и същ е, като волейболна топка.
Репонсът е респонс и за респондващият, и за респонднатият, пак на принципа на волейболната топка, едно и също е и за двете страни.
Демек, това което изпраща клиентът и съответно получава сървът, и за двете страни е един и същ Request.
И съответно и за Respons-ът.
Каквото подадеш е рекуест и за двете страни, каквото отговориш е респонс и за двете страни.
Но ако гледаме на дадените рекуести и респонси само от гледна точка на HTTP протоколът.
RequestInterface
provides the general representation of an HTTP request message. However, server-side requests need additional treatment, due to the nature of the server-side environment.
Демек, когато сървът получи HTTP рекуест (RequestInterface
), той от своя страна създава нов обект от ServerRequestInterface
според своите си настройки и environment…
Това вече е ServerRequestInterface
рекуест обект.
Демек, едното е така да се каже чистият HTTP рекуест, другото – нещо като разширената му версия според сърва, за да може да работим с него, с HTTP рекуеста. В какъв смисъл „разширената му версия“? В смисъл такъв, че например данните от HTTP рекуеста са парсирани и така да се каже, разпределени по масиви като $_GET, $_POST, $_COOKIE…
Messages Immutability
Messages are considered immutable; all methods that might change state MUST be implemented such that they retain the internal state of the current message and return an instance that contains the changed state.
Демек, нищо не променяш от това, което са ти подали, пазиш го непромененo. От него клонираш нов обект, в него променяш, и него използваш. Оригиналният запазваш напокътнат. На клонираният може всичко да променяш, но оригиналният трябва да си остане напокътнат.
PSR-7 препоръчва как едно PHP приложение, чисто откъм програмна страна, да приема HTTP заявките от клиента, и да създава HTTP отговорите, като задава интерфейси, които задават цялостна структура на класовете и методите, вършещи това.
This specification defines interfaces for the HTTP messages (request and response) Psr\Http\Message\RequestInterface
and Psr\Http\Message\ResponseInterface
respectively. Това сa двата интерфейса, които класовете за приемане на HTTP заявките и изпращане на HTTP отговорите, трябва да имплементират.
И двата наследяват Psr\Http\Message\MessageInterface
Но една такава заявка (Request) съдържа и много информация, извън самият HTTP протокол, информация свързана със самият сървър, демек това, което в PHP е в суперглобалният масив $_SERVER.
Затова трябва да имаме интерфейс Psr\Http\Message\ServerRequestInterface
, наследяващ RequestInterface
и работещ с информация от HTTP заявката, като:
- The values represented in $_SERVER
- Any cookies provided (generally via $_COOKIE)
- Query string arguments (generally via $_GET, or as parsed via parse_str())
- Upload files, if any (as represented by $_FILES)
- Deserialized body parameters (generally from $_POST)
Concerning headers
Headers are retrieved by name from classes implementing the MessageInterface
in a case-insensitive manner. For example, retrieving the foo
header will return the same result as retrieving the FoO
header. Similarly, setting the Foo
header will overwrite any previously set foo
header value.
Методите за извличане и сетване на хедъри(те) на дадено HTTP съобщение се задават в Psr\Http\Message\MessageInterface
Интересно е, че при извличане/променяне на хедър (което става по име), името му е case insensitive, демек няма разлика между FoO и fOO що се отнася до името на даденият хедър.
Streams
Не винаги е безопасно цялото боди на рекуеста да се запазва в променлива, защото може да бъде огромен и това да претовари сърва като му изчерпи паметта. Или просто да надвиши настройки на PHP като upload_max_filesize или post_max_size.
Without streams, opening a 20MB file will consume 20MB of memory.
Също, относно immutability. Няма такава за streams.
Защо?
Защото за да работиш със стрийм по принцип, трябва да можеш например динамично да задаваш поинтъра, където си в момента…
Стриймовете не са като обикновеният рекуест, който го получаваш an block, на цяло, на веднъж. Те са нещо динамично, пристигащо на части, така да се каже. Няма как от началото още да знаеш какво ще съдържа като цяло.
…immutability is impossible to enforce, as any code that interacts with the resource can potentially change its state (including cursor position, contents, and more)...
Демек, самото взаимодействие със стрийма може да го промени.
Достъпът до стриймовете могат да са read only, write only, randomly accessed
Server request
Сами по себе си RequestInterface обектите съдържат информация само и чисто за самият HTTP рекуест. Освен RequestInterface обект, имаме и ServerRequestInterface обект, който добавя към гореспоменатият обект още информация, свързана с конкретният сърв.
Литература:
https://www.php-fig.org/psr/psr-7/
https://www.php-fig.org/psr/psr-7/meta/#71-validation-of-header-names-and-values