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