On this page
Reader
HTTP Clients
Several operations in laminas-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,
Laminas\Feed\Reader\Http\ClientInterface
and HeaderAwareClientInterface
:
namespace Laminas\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:
$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:
$headers = [
'Accept' => [ 'application/rss+xml' ],
];
A call to get()
should yield a response.
ResponseInterface and HeaderAwareResponseInterface
Responses are modeled using Laminas\Feed\Reader\Http\ResponseInterface
and
HeaderAwareResponseInterface
:
namespace Laminas\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
laminas-feed ships with a generic ResponseInterface
implementation,
Laminas\Feed\Http\Response
. It implements HeaderAwareResponseInterface
, and
defines the following constructor:
namespace Laminas\Feed\Reader\Http;
class Response implements HeaderAwareResponseInterface
{
/**
* @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 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 Laminas\Feed\Reader\Psr7ResponseDecorator
:
namespace Laminas\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:
$ composer require psr/http-message
laminas-http
We also provide a laminas-http client decorator,
Laminas\Feed\Reader\Http\LaminasHttpClientDecorator
:
namespace Laminas\Feed\Reader\Http;
use Laminas\Http\Client as HttpClient;
class LaminasHttpClientDecorator 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
laminas-http response returned, including status, body, and headers.
laminas-http is the default implementation assumed by Laminas\Feed\Reader\Reader
,
but is not installed by default. You may install it using composer:
$ composer require laminas/laminas-http
Providing a client to Reader
By default, Laminas\Feed\Reader\Reader
will lazy load a laminas-http client. If you
have not installed laminas-http, however, PHP will raise an error indicating the
class is not found!
As such, you have two options:
- Install laminas-http:
composer require laminas/laminas-http
. - Inject the
Reader
with your own HTTP client.
To accomplish the second, you will need an implementation of
Laminas\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:
use My\Http\Psr7FeedClient;
use Laminas\Feed\Reader\Reader;
Reader::setHttpClient(new Psr7FeedClient());
Your client will then be used for all import()
and findFeedLinks()
operations.