1### PSR-7 Usage 2 3All PSR-7 applications comply with these interfaces 4They were created to establish a standard between middleware implementations. 5 6> `RequestInterface`, `ServerRequestInterface`, `ResponseInterface` extend `MessageInterface` because the `Request` and the `Response` are `HTTP Messages`. 7> When using `ServerRequestInterface`, both `RequestInterface` and `Psr\Http\Message\MessageInterface` methods are considered. 8 9 10The following examples will illustrate how basic operations are done in PSR-7. 11 12##### Examples 13 14 15For this examples to work (at least) a PSR-7 implementation package is required. (eg: zendframework/zend-diactoros, guzzlehttp/psr7, slim/slim, etc) 16All PSR-7 implementations should have the same behaviour. 17 18The following will be assumed: 19`$request` is an object of `Psr\Http\Message\RequestInterface` and 20 21`$response` is an object implementing `Psr\Http\Message\RequestInterface` 22 23 24### Working with HTTP Headers 25 26#### Adding headers to response: 27 28```php 29$response->withHeader('My-Custom-Header', 'My Custom Message'); 30``` 31 32#### Appending values to headers 33 34```php 35$response->withAddedHeader('My-Custom-Header', 'The second message'); 36``` 37 38#### Checking if header exists: 39 40```php 41$request->hasHeader('My-Custom-Header'); // will return false 42$response->hasHeader('My-Custom-Header'); // will return true 43``` 44 45> Note: My-Custom-Header was only added in the Response 46 47#### Getting comma-separated values from a header (also applies to request) 48 49```php 50// getting value from request headers 51$request->getHeaderLine('Content-Type'); // will return: "text/html; charset=UTF-8" 52// getting value from response headers 53$response->getHeaderLine('My-Custom-Header'); // will return: "My Custom Message; The second message" 54``` 55 56#### Getting array of value from a header (also applies to request) 57```php 58// getting value from request headers 59$request->getHeader('Content-Type'); // will return: ["text/html", "charset=UTF-8"] 60// getting value from response headers 61$response->getHeader('My-Custom-Header'); // will return: ["My Custom Message", "The second message"] 62``` 63 64#### Removing headers from HTTP Messages 65```php 66// removing a header from Request, removing deprecated "Content-MD5" header 67$request->withoutHeader('Content-MD5'); 68 69// removing a header from Response 70// effect: the browser won't know the size of the stream 71// the browser will download the stream till it ends 72$response->withoutHeader('Content-Length'); 73``` 74 75### Working with HTTP Message Body 76 77When working with the PSR-7 there are two methods of implementation: 78#### 1. Getting the body separately 79 80> This method makes the body handling easier to understand and is useful when repeatedly calling body methods. (You only call `getBody()` once). Using this method mistakes like `$response->write()` are also prevented. 81 82```php 83$body = $response->getBody(); 84// operations on body, eg. read, write, seek 85// ... 86// replacing the old body 87$response->withBody($body); 88// this last statement is optional as we working with objects 89// in this case the "new" body is same with the "old" one 90// the $body variable has the same value as the one in $request, only the reference is passed 91``` 92 93#### 2. Working directly on response 94 95> This method is useful when only performing few operations as the `$request->getBody()` statement fragment is required 96 97```php 98$response->getBody()->write('hello'); 99``` 100 101### Getting the body contents 102 103The following snippet gets the contents of a stream contents. 104> Note: Streams must be rewinded, if content was written into streams, it will be ignored when calling `getContents()` because the stream pointer is set to the last character, which is `\0` - meaning end of stream. 105```php 106$body = $response->getBody(); 107$body->rewind(); // or $body->seek(0); 108$bodyText = $body->getContents(); 109``` 110> Note: If `$body->seek(1)` is called before `$body->getContents()`, the first character will be ommited as the starting pointer is set to `1`, not `0`. This is why using `$body->rewind()` is recommended. 111 112### Append to body 113 114```php 115$response->getBody()->write('Hello'); // writing directly 116$body = $request->getBody(); // which is a `StreamInterface` 117$body->write('xxxxx'); 118``` 119 120### Prepend to body 121Prepending is different when it comes to streams. The content must be copied before writing the content to be prepended. 122The following example will explain the behaviour of streams. 123 124```php 125// assuming our response is initially empty 126$body = $repsonse->getBody(); 127// writing the string "abcd" 128$body->write('abcd'); 129 130// seeking to start of stream 131$body->seek(0); 132// writing 'ef' 133$body->write('ef'); // at this point the stream contains "efcd" 134``` 135 136#### Prepending by rewriting separately 137 138```php 139// assuming our response body stream only contains: "abcd" 140$body = $response->getBody(); 141$body->rewind(); 142$contents = $body->getContents(); // abcd 143// seeking the stream to beginning 144$body->rewind(); 145$body->write('ef'); // stream contains "efcd" 146$body->write($contents); // stream contains "efabcd" 147``` 148 149> Note: `getContents()` seeks the stream while reading it, therefore if the second `rewind()` method call was not present the stream would have resulted in `abcdefabcd` because the `write()` method appends to stream if not preceeded by `rewind()` or `seek(0)`. 150 151#### Prepending by using contents as a string 152```php 153$body = $response->getBody(); 154$body->rewind(); 155$contents = $body->getContents(); // efabcd 156$contents = 'ef'.$contents; 157$body->rewind(); 158$body->write($contents); 159``` 160