This repository has been archived on 2025-01-19. You can view files and clone it, but cannot push or open issues or pull requests.
drupalcampbristol/web/vendor/zendframework/zend-feed/doc/book/http-clients.md

237 lines
6.2 KiB
Markdown
Raw Normal View History

2017-04-13 14:53:35 +00:00
# HTTP Clients and zend-feed
Several operations in zend-feed's Reader subcomponent require an HTTP client:
- importing a feed
- finding links in a feed
In order to allow developers a choice in HTTP clients, the subcomponent defines
several interfaces and classes. Elsewhere in the documentation, we reference
where an HTTP client may be used; this document details what constitutes an HTTP
client and its behavior, and some of the concrete classes available within the
component for implementing this behavior.
## ClientInterface and HeaderAwareClientInterface
First, we define two interfaces for clients,
`Zend\Feed\Reader\Http\ClientInterface` and `HeaderAwareClientInterface`:
```php
namespace Zend\Feed\Reader\Http;
interface ClientInterface
{
/**
* Make a GET request to a given URL.
*
* @param string $url
* @return ResponseInterface
*/
public function get($url);
}
interface HeaderAwareClientInterface extends ClientInterface
{
/**
* Make a GET request to a given URL.
*
* @param string $url
* @param array $headers
* @return ResponseInterface
*/
public function get($url, array $headers = []);
}
```
The first is header-agnostic, and assumes that the client will simply perform an
HTTP GET request. The second allows providing headers to the client; typically,
these are used for HTTP caching headers. `$headers` must be in the following
structure:
```php
$headers = [
'X-Header-Name' => [
'header',
'values',
],
];
```
i.e., each key is a header name, and each value is an array of values for that
header. If the header represents only a single value, it should be an array with
that value:
```php
$headers = [
'Accept' => [ 'application/rss+xml' ],
];
```
A call to `get()` should yield a *response*.
## ResponseInterface and HeaderAwareResponseInterface
Responses are modeled using `Zend\Feed\Reader\Http\ResponseInterface` and
`HeaderAwareResponseInterface`:
```php
namespace Zend\Feed\Reader\Http;
class ResponseInterface
{
/**
* Retrieve the status code.
*
* @return int
*/
public function getStatusCode();
/**
* Retrieve the response body contents.
*
* @return string
*/
public function getBody();
}
class HeaderAwareResponseInterface extends ResponseInterface
{
/**
* Retrieve a named header line.
*
* Retrieve a header by name; all values MUST be concatenated to a single
* line. If no matching header is found, return the $default value.
*
* @param string $name
* @param null|string $default
* @return string
public function getHeaderLine($name, $default = null);
}
```
Internally, `Reader` will typehint against `ClientInterface` for the bulk of
operations. In some cases, however, certain capabilities are only possible if
the response can provide headers (e.g., for caching); in such cases, it will
check the instance against `HeaderAwareResponseInterface`, and only call
`getHeaderLine()` if it matches.
## Response
zend-feed ships with a generic `ResponseInterface` implementation,
`Zend\Feed\Http\Response`. It implements `HeaderAwareResponseInterface`, and
defines the following constructor:
```php
namespace Zend\Feed\Reader\Http;
class Response implements HeaderAwareResponseInterface
{
/**
* Constructor
*
* @param int $statusCode Response status code
* @param string $body Response body
* @param array $headers Response headers, if available
*/
public function __construct($statusCode, $body, array $headers = []);
}
```
## PSR-7 Response
[PSR-7](http://www.php-fig.org/psr/psr-7/) defines a set of HTTP message
interfaces, but not a client interface. To facilitate wrapping an HTTP client
that uses PSR-7 messages, we provide `Zend\Feed\Reader\Psr7ResponseDecorator`:
```php
namespace Zend\Feed\Reader\Http;
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
class Psr7ResponseDecorator implements HeaderAwareResponseInterface
{
/**
* @param PsrResponseInterface $response
*/
public function __construct(PsrResponseInterface $response);
/**
* @return PsrResponseInterface
*/
public function getDecoratedResponse();
}
```
Clients can then take the PSR-7 response they receive, pass it to the decorator,
and return the decorator.
To use the PSR-7 response, you will need to add the PSR-7 interfaces to your
application, if they are not already installed by the client of your choice:
```bash
$ composer require psr/http-message
```
## zend-http
We also provide a zend-http client decorator,
`Zend\Feed\Reader\Http\ZendHttpClientDecorator`:
```php
namespace Zend\Feed\Reader\Http;
use Zend\Http\Client as HttpClient;
class ZendHttpClientDecorator implements HeaderAwareClientInterface
{
/**
* @param HttpClient $client
*/
public function __construct(HttpClient $client);
/**
* @return HttpClient
*/
public function getDecoratedClient();
}
```
Its `get()` implementation returns a `Response` instance seeded from the
zend-http response returned, including status, body, and headers.
zend-http is the default implementation assumed by `Zend\Feed\Reader\Reader`,
but *is not installed by default*. You may install it using composer:
```bash
$ composer require zendframework/zend-http
```
## Providing a client to Reader
By default, `Zend\Feed\Reader\Reader` will lazy load a zend-http client. If you
have not installed zend-http, however, PHP will raise an error indicating the
class is not found!
As such, you have two options:
1. Install zend-http: `composer require zendframework/zend-http`.
2. Inject the `Reader` with your own HTTP client.
To accomplish the second, you will need an implementation of
`Zend\Feed\Reader\Http\ClientInterface` or `HeaderAwareClientInterface`, and an
instance of that implementation. Once you do, you can use the static method
`setHttpClient()` to inject it.
As an example, let's say you've created a PSR-7-based implementation named
`My\Http\Psr7FeedClient`. You could then do the following:
```php
use My\Http\Psr7FeedClient;
use Zend\Feed\Reader\Reader;
Reader::setHttpClient(new Psr7FeedClient());
```
Your client will then be used for all `import()` and `findFeedLinks()`
operations.