comparison vendor/zendframework/zend-feed/doc/book/http-clients.md @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 # HTTP Clients and zend-feed
2
3 Several operations in zend-feed's Reader subcomponent require an HTTP client:
4
5 - importing a feed
6 - finding links in a feed
7
8 In order to allow developers a choice in HTTP clients, the subcomponent defines
9 several interfaces and classes. Elsewhere in the documentation, we reference
10 where an HTTP client may be used; this document details what constitutes an HTTP
11 client and its behavior, and some of the concrete classes available within the
12 component for implementing this behavior.
13
14 ## ClientInterface and HeaderAwareClientInterface
15
16 First, we define two interfaces for clients,
17 `Zend\Feed\Reader\Http\ClientInterface` and `HeaderAwareClientInterface`:
18
19 ```php
20 namespace Zend\Feed\Reader\Http;
21
22 interface ClientInterface
23 {
24 /**
25 * Make a GET request to a given URL.
26 *
27 * @param string $url
28 * @return ResponseInterface
29 */
30 public function get($url);
31 }
32
33 interface HeaderAwareClientInterface extends ClientInterface
34 {
35 /**
36 * Make a GET request to a given URL.
37 *
38 * @param string $url
39 * @param array $headers
40 * @return ResponseInterface
41 */
42 public function get($url, array $headers = []);
43 }
44 ```
45
46 The first is header-agnostic, and assumes that the client will simply perform an
47 HTTP GET request. The second allows providing headers to the client; typically,
48 these are used for HTTP caching headers. `$headers` must be in the following
49 structure:
50
51 ```php
52 $headers = [
53 'X-Header-Name' => [
54 'header',
55 'values',
56 ],
57 ];
58 ```
59
60 i.e., each key is a header name, and each value is an array of values for that
61 header. If the header represents only a single value, it should be an array with
62 that value:
63
64 ```php
65 $headers = [
66 'Accept' => [ 'application/rss+xml' ],
67 ];
68 ```
69
70 A call to `get()` should yield a *response*.
71
72 ## ResponseInterface and HeaderAwareResponseInterface
73
74 Responses are modeled using `Zend\Feed\Reader\Http\ResponseInterface` and
75 `HeaderAwareResponseInterface`:
76
77 ```php
78 namespace Zend\Feed\Reader\Http;
79
80 class ResponseInterface
81 {
82 /**
83 * Retrieve the status code.
84 *
85 * @return int
86 */
87 public function getStatusCode();
88
89 /**
90 * Retrieve the response body contents.
91 *
92 * @return string
93 */
94 public function getBody();
95 }
96
97 class HeaderAwareResponseInterface extends ResponseInterface
98 {
99 /**
100 * Retrieve a named header line.
101 *
102 * Retrieve a header by name; all values MUST be concatenated to a single
103 * line. If no matching header is found, return the $default value.
104 *
105 * @param string $name
106 * @param null|string $default
107 * @return string
108 public function getHeaderLine($name, $default = null);
109 }
110 ```
111
112 Internally, `Reader` will typehint against `ClientInterface` for the bulk of
113 operations. In some cases, however, certain capabilities are only possible if
114 the response can provide headers (e.g., for caching); in such cases, it will
115 check the instance against `HeaderAwareResponseInterface`, and only call
116 `getHeaderLine()` if it matches.
117
118 ## Response
119
120 zend-feed ships with a generic `ResponseInterface` implementation,
121 `Zend\Feed\Http\Response`. It implements `HeaderAwareResponseInterface`, and
122 defines the following constructor:
123
124 ```php
125 namespace Zend\Feed\Reader\Http;
126
127 class Response implements HeaderAwareResponseInterface
128 {
129 /**
130 * Constructor
131 *
132 * @param int $statusCode Response status code
133 * @param string $body Response body
134 * @param array $headers Response headers, if available
135 */
136 public function __construct($statusCode, $body, array $headers = []);
137 }
138 ```
139
140 ## PSR-7 Response
141
142 [PSR-7](http://www.php-fig.org/psr/psr-7/) defines a set of HTTP message
143 interfaces, but not a client interface. To facilitate wrapping an HTTP client
144 that uses PSR-7 messages, we provide `Zend\Feed\Reader\Psr7ResponseDecorator`:
145
146 ```php
147 namespace Zend\Feed\Reader\Http;
148
149 use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
150
151 class Psr7ResponseDecorator implements HeaderAwareResponseInterface
152 {
153 /**
154 * @param PsrResponseInterface $response
155 */
156 public function __construct(PsrResponseInterface $response);
157
158 /**
159 * @return PsrResponseInterface
160 */
161 public function getDecoratedResponse();
162 }
163 ```
164
165 Clients can then take the PSR-7 response they receive, pass it to the decorator,
166 and return the decorator.
167
168 To use the PSR-7 response, you will need to add the PSR-7 interfaces to your
169 application, if they are not already installed by the client of your choice:
170
171 ```bash
172 $ composer require psr/http-message
173 ```
174
175 ## zend-http
176
177 We also provide a zend-http client decorator,
178 `Zend\Feed\Reader\Http\ZendHttpClientDecorator`:
179
180 ```php
181 namespace Zend\Feed\Reader\Http;
182
183 use Zend\Http\Client as HttpClient;
184
185 class ZendHttpClientDecorator implements HeaderAwareClientInterface
186 {
187 /**
188 * @param HttpClient $client
189 */
190 public function __construct(HttpClient $client);
191
192 /**
193 * @return HttpClient
194 */
195 public function getDecoratedClient();
196 }
197 ```
198
199 Its `get()` implementation returns a `Response` instance seeded from the
200 zend-http response returned, including status, body, and headers.
201
202 zend-http is the default implementation assumed by `Zend\Feed\Reader\Reader`,
203 but *is not installed by default*. You may install it using composer:
204
205 ```bash
206 $ composer require zendframework/zend-http
207 ```
208
209 ## Providing a client to Reader
210
211 By default, `Zend\Feed\Reader\Reader` will lazy load a zend-http client. If you
212 have not installed zend-http, however, PHP will raise an error indicating the
213 class is not found!
214
215 As such, you have two options:
216
217 1. Install zend-http: `composer require zendframework/zend-http`.
218 2. Inject the `Reader` with your own HTTP client.
219
220 To accomplish the second, you will need an implementation of
221 `Zend\Feed\Reader\Http\ClientInterface` or `HeaderAwareClientInterface`, and an
222 instance of that implementation. Once you do, you can use the static method
223 `setHttpClient()` to inject it.
224
225 As an example, let's say you've created a PSR-7-based implementation named
226 `My\Http\Psr7FeedClient`. You could then do the following:
227
228 ```php
229 use My\Http\Psr7FeedClient;
230 use Zend\Feed\Reader\Reader;
231
232 Reader::setHttpClient(new Psr7FeedClient());
233 ```
234
235 Your client will then be used for all `import()` and `findFeedLinks()`
236 operations.