IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

8. diel - Štandardy jazyka PHP - PSR-7 (Všeobecná špecifikácie a prúdy)

V predchádzajúcej lekcii, Štandardy jazyka PHP - PSR-6 (cachovací rozhranie) , sme si vysvetlili podstatu cachovacího rozhranie a niektoré dôležité pojmy s ním súvisiace.

PSR-7, ktorý sa zaoberá rozhraním pre HTTP dotazy a odpovede, je trochu obsiahlejší a v niekoľkých nasledujúcich lekciách sa budeme venovať práve jemu.

Pre lepšie pochopenie štandardu si môžeme prezrieť nasledujúce RFC:

Štruktúra

HTTP protokol je bezpochyby základom webu. Webové prehliadače a HTTP klienti (napríklad cURL) vytvára HTTP otázky, na ktoré odpovedá server pomocou HTTP odpovede. Tieto správy sú pre koncového užívateľa pre jednoduchosť a prehľadnosť zovšeobecnené, ale ak nejakú aplikáciu vyvíjame, spravidla potrebujeme presne poznať ich štruktúru a tiež spôsob, ako s nimi manipulovať.

Každý HTTP dotaz má špecifickú štruktúru:

POST /path HTTP/1.1
Host: example.com

foo=bar&baz=bat

Prvý riadok obsahuje:

  • metódu dotazu,
  • cieľ (väčšinou absolútnu URI cestu alebo cestu na web) a
  • verziu HTTP protokolu

Za ním nasleduje jedna alebo viac hlavičiek, prázdny riadok a potom telo dotazu.

Podobná je aj štruktúra HTTP odpovede:

HTTP/1.1 200 OK
Content-Type: text/plain

Toto je tělo odpovědi

Prvý čiže "stavový" riadok obsahuje v tomto poradí:

  • verziu HTTP protokolu,
  • stavový kód a
  • tzv. reason phrase

Reason phrase je slovná hodnota a pre človeka stráviteľnejšie vysvetlenie daného stavového kódu.

Podobne ako v HTTP dotaze nasleduje aj v odpovedi hlavička, prázdny riadok a telo odpovede.

Špecifikácia

Uvedieme si špecifikácie správ, HTTP hlavičiek a prúdov (streamov).

Správy

Pod pojmom HTTP správa je myslený buď požiadavka zo strany klienta na server, alebo odpoveď servera klientovi. Oba druhy majú definované svoje vlastné rozhranie a síce Psr\Http\Message\RequestInterface a Psr\Http\Message\ResponseInterface.

Obe tieto rozhrania rozširujú Psr\Http\Message\MessageInterface. Zatiaľ čo toto predvolené rozhranie MÔŽE byť implementované priamo, implementátori (tí, čo rozhranie implementujú) BY MALI implementovať nadväzujúce Psr\Http\Message\RequestInterface a Psr\Http\Message\ResponseInterface.

Tu sme si uviedli plnú cestu k rozhraním požiadaviek i odpovedí. Ďalej budeme Psr\Http\Message pre prehľadnosť vynechávať.

HTTP hlavičky

Ukážeme si hlavičky case-insensitive, s viacerými hodnotami a tiež hosť header.

Case-insensitive hlavičky

HTTP správy obsahujú case-insensitive hlavičky. Tie sú vyhľadávané pomocou názvu z tried implementujúcich MessageInterface nehľadiac na veľkosť písmen. Výsledok je rovnaký, či už sa snažíme vyhľadať foo alebo napríklad FoO. Rovnako tak sa hlavička foo prepíše, ak neskôr nastavíme Foo:

$message = $message->withHeader('foo', 'bar');

echo $message->getHeaderLine('foo');
// Vypíše se „bar“

echo $message->getHeaderLine('FOO');
// Vypíše se „bar“

$message = $message->withHeader('fOO', 'baz');
echo $message->getHeaderLine('foo');
// Vypíše se „baz“
Aj keď hlavičky môžu byť hľadané bez dôrazu na veľkosť písmen, pôvodný zápis MUSÍ byť implementácií zachovaný, konkrétne pri volaní getHeaders().
Niektoré (nie celkom vyhovujúce) HTTP aplikácie môžu závisieť od veľkosti písmen, takže je pre užívateľov užitočné, aby ju mohol pri vytváraní HTTP požiadavky presne definovať.

Hlavičky s viacerými hodnotami

Aby bolo možné pracovať s viacerými hodnotami a zároveň zachovať výhody práce s hlavičkami ako s reťazcami, hlavičky môžu byť získané z inštancie MessageInterface ako pole alebo string. Použitím metódy getHeaderLine() získame všetky (case-insensitive) hodnoty hlavičky zreťazené pomocou čiarky. Pomocou funkcie getHeader() získame pole všetkých hodnôt (opäť case-insensitive):

$message = $message
    ->withHeader('foo', 'bar')
    ->withAddedHeader('foo', 'baz');

$header = $message->getHeaderLine('foo');
// $header obsahuje: 'bar,baz'

$header = $message->getHeader('foo');
// ['bar', 'baz']

Nie všetky hodnoty odosielané v hlavičkách môžu byť zlúčia pomocou čiarky, napríklad Set-Cookie.

Ak pracujeme s týmito konkrétnymi hlavičkami, ako používatelia tried založených na MessageInterface by sme MALI spoliehať skôr na getHeader() namiesto getHeaderLine().

Hosť header

V otázkach hosť header typicky napodobňuje hosť komponent URI rovnako ako hosť používaný pri nadväzovaní TCP spojenia. Špecifikácie HTTP ale umožňuje tieto dve situácie od seba navzájom rozlíšiť.

Ak pri konštrukcii nie je dodaný hosť header, implementácia sa MUSÍ pokúsiť tento header nastaviť podľa URI.

RequestInterface::withUri() v predvolenom nastavení nahradí hosť header požiadavke hosť header zodpovedajúcim hosť komponente odovzdaného UriInterface.

Je možné zvoliť, aby bol pôvodný stav hosť header zachovaný pomocou druhého argumentu funkcie ($preserveHost). Pokiaľ tento argument nastavíme na TRUE a správa už nejaký hosť header obsahuje, požiadavku ho aktualizovať nebude.

Nasledujúca tabuľka ilustruje, čo getHeaderLine('Host') v rôznych situáciách vráti na požiadavku vrátený pomocou withUri() s argumentom $preserveHost nastaveným ako TRUE.

REQUEST HOST HEADER ★ 1 REQUEST HOST Komponenty ★ 2 URI HOST Komponenty ★ 3 VÝSLEDOK
"" "" "" ""
"" foo.com "" foo.com
"" foo.com bar.com foo.com
foo.com "" bar.com foo.com
foo.com bar.com baz.com foo.com
1 - hodnota hosť header pred operáciou

2 - hosť komponenta URI vytvorená v požiadavke pred operáciou

3 - hosť komponent URI vytvorená pomocou withUri ()

Prúdy (streams)

HTTP správy sa skladajú z tzv. Start-line, hlavičiek a tela. Telo správy môže byť rôznych veľkostí, od jedného riadku až po extrémne obsiahla dáta.

Pokus o reprezentáciu dlhého tela ako reťazce môže jednoducho vyústiť vo väčšej obsadenie pamäti, než bolo pôvodne zamýšľané, pretože v nej musí byť uložené úplne celé telo. Pri takomto pokuse uložiť do pamäti, či už požiadavky alebo odpovede, je znemožnená práca implementácia s telom.

Keď zapisujeme do prúdu dát alebo z neho čítame, sú pomocou rozhrania StreamInterface detaily o implementácii schované. V situáciách, kedy je pre nás implementácia pomocou reťazca výhodná, môžu byť použité vstavané prúdy ako php://memory a php://temp.

StreamInterface vystavuje svoje schopnosti pomocou troch metód:

  • isReadable(),
  • isWritable() a
  • isSeekable().

Tieto metódy môžu byť použité ďalšími funkciami (metódami, rozhraniami, ...) pre zistenie, či prúd vyhovuje všetkým nárokom a podmienkam.

Každá inštancia prúdu má rôznorodé schopnosti a môže byť:

  • read-only (len pre čítanie)
  • write-only (len pre zápis)
  • read-write (čítanie aj zápis)

Tiež môžu povoliť náhodný prístup (hľadanie spredu i zozadu), alebo iba sekvenčný prístup (napríklad v prípade socketu, pipe (rúry) alebo callback-based prúdu).

Rozhranie StreamInterface definuje ešte jednu metódu, a to __toString(). Je určená k zjednodušeniu získania alebo emitovanie celého obsahu tela naraz.

Na rozdiel od ostatných rozhrania týkajúcich sa HTTP správ StreamInterface nezabezpečuje nemennosť dát (immutability).

Ak sú použité tzv. Wrappovací funkcie, nemennosť je nemožné zaistiť, pretože akýkoľvek kód, ktorý pracuje so zdrojom, môže teoreticky zmeniť jeho stav (a to vrátane polohy kurzora, obsahu a mnohých ďalšieho). Autor odporúča, aby používatelia pri implementácii rozhrania používali iba read-only streamy pre serverové požiadavky a otázky klienta.

Používatelia by si mali byť vedomí, že inštancie prúdu môže byť vymeniteľné (mutable) a ako taká môže zmeniť stav správy. Ak sme na pochybách, je vhodné vytvoriť novú inštanciu a priložiť ju k správe, aby sme stav vynútili.

V ďalšej lekcii, Štandardy jazyka PHP - PSR-7 (Rozhranie HTTP správ a prúdov) , sa budeme zaoberať rozhraniami pre dátové prúdy a HTTP správy, jednotlivými funkciami a ich použitím.


 

Predchádzajúci článok
Štandardy jazyka PHP - PSR-6 (cachovací rozhranie)
Všetky články v sekcii
Štandardy jazyka PHP
Preskočiť článok
(neodporúčame)
Štandardy jazyka PHP - PSR-7 (Rozhranie HTTP správ a prúdov)
Článok pre vás napísala Miroslava Škutová
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
.
Aktivity