1 |
efrain |
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 |
```
|