| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,159 @@ |
| 1 |
+### PSR-7 Usage |
|
| 2 |
+ |
|
| 3 |
+All PSR-7 applications comply with these interfaces |
|
| 4 |
+They 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 |
+ |
|
| 10 |
+The following examples will illustrate how basic operations are done in PSR-7. |
|
| 11 |
+ |
|
| 12 |
+##### Examples |
|
| 13 |
+ |
|
| 14 |
+ |
|
| 15 |
+For this examples to work (at least) a PSR-7 implementation package is required. (eg: zendframework/zend-diactoros, guzzlehttp/psr7, slim/slim, etc) |
|
| 16 |
+All PSR-7 implementations should have the same behaviour. |
|
| 17 |
+ |
|
| 18 |
+The 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 |
+ |
|
| 77 |
+When 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 |
+ |
|
| 103 |
+The 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 |
|
| 121 |
+Prepending is different when it comes to streams. The content must be copied before writing the content to be prepended. |
|
| 122 |
+The 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 |
+``` |