Zend\Feed is a powerful library for discovering, reading and writing RSS feeds in various formats (we’re only interested in discovery and reading here). By default Zend\Feed\Reader\Reader, which is a collection of static methods to access feed reading and discovery functionality, uses a Zend\Http\Client to handle HTTP communication. Unfortunately Zend\Http\Client has some issues when being used in the wild, such as: “Incorrect handling of negative MaxAge cookie attribute” or “ChunkedBody decoding with Curl Adapter” or some others.

That’s why we tried to integrate Zend\Feed\Reader\Reader with a different HTTP client library that was already part of the project: Guzzle. Guzzle is a powerful HTTP client and it supports PSR-7 – the PHP-FIG standard for HTTP message interfaces. Based on this standard integration worked like a charm, because there is a hardly documented PSR-7 compatibility layer included in Zend\Feed\Reader – the Zend\Feed\Reader\Http\Psr7ResponseDecorator.

Integrating Guzzle into Zend\Feed\Reader\Reader just required one class though – an implementation of Zend\Feed\Reader\Http\ClientInterface which is one of the easiest interfaces you can think of:

namespace Zend\Feed\Reader\Http;

interface ClientInterface
{
    /**
     * Make a GET request to a given URI
     *
     * @param  string $uri
     * @return ResponseInterface
     */
    public function get($uri);
}

Our AppBundle\Feed\GuzzleClient turned out to be as simple as:

namespace AppBundle\Feed;

use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface as GuzzleClientInterface;
use Zend\Feed\Reader\Http\ClientInterface as FeedReaderHttpClientInterface;
use Zend\Feed\Reader\Http\Psr7ResponseDecorator;

/**
 * Class GuzzleClient
 *
 * @package AppBundle\Feed
 */
class GuzzleClient implements FeedReaderHttpClientInterface
{
    /**
     * @var GuzzleClientInterface
     */
    private $client;

    /**
     * GuzzleClient constructor.
     *
     * @param GuzzleClientInterface|null $client
     */
    public function __construct(GuzzleClientInterface $client = null)
    {
        $this->client = $client ?: new Client();
    }

    /**
     * {@inheritdoc}
     */
    public function get($uri)
    {
        $response = $this->client->request('GET', $uri);

        return new Psr7ResponseDecorator($response);
    }
}

GuzzleHttp\ClientInterface::request() returns a Psr\Http\Message\ResponseInterface which can directly be put into an instance of Zend\Feed\Reader\Http\Psr7ResponseDecorator.

Now we could just replace Zend\Feed\Reader\Reader‘s HTTP client with our new Guzzle decorator:

Zend\Feed\Reader\Reader::setHttpClient(new AppBundle\Feed\GuzzleClient());

That’s it – feed discovery (Zend\Feed\Reader\Reader::findFeedLinks($uri)) and feed reading (Zend\Feed\Reader\Reader::import($uri)) now communicate via the more robust Guzzle library instead of Zend\Http\Client.[/fusion_builder_column][/fusion_builder_row][/fusion_builder_container]