Skip to content

Instantly share code, notes, and snippets.

@Thinkscape
Last active October 4, 2022 18:30
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Thinkscape/43499cfafda1af8f606d to your computer and use it in GitHub Desktop.
Save Thinkscape/43499cfafda1af8f606d to your computer and use it in GitHub Desktop.
getEffectiveUrl() replacement for Guzzle 6.*
<?php
/*
$response->getEffectiveUrl() solution for Guzzle 6
--------------------------------------------------------------
In Guzzle 3, 4 and 5 one could use $response->getEffectiveUrl() to retrieve
the last URL in a chain of HTTP redirects.
Guzzle 6 uses PSR7 interfaces which do not support this use case, however
we can still manipulate response headers to store additional information.
This is a standard practice among proxies, caches, authentication gateways
and other internet services.
The effective URL is stored in response header X-GUZZLE-EFFECTIVE-URL
@link http://stackoverflow.com/questions/30682307/how-to-read-the-response-effective-url-in-guzzle-6-0/31962446#31962446
*/
use GuzzleHttp\Client;
use Thinkscape\Guzzle\EffectiveUrlMiddleware;
// Add the middleware to stack and create guzzle client
$stack = HandlerStack::create();
$stack->push(EffectiveUrlMiddleware::middleware());
$client = new Client(['handler' => $stack]);
// Test it out!
$response = $client->get('http://bit.ly/1N2DZdP');
echo $response->getHeaderLine('X-GUZZLE-EFFECTIVE-URL');
<?php
namespace Thinkscape\Guzzle;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
class EffectiveUrlMiddleware
{
/**
* @var Callable
*/
protected $nextHandler;
/**
* @var string
*/
protected $headerName;
/**
* @param callable $nextHandler
* @param string $headerName The header name to use for storing effective url
*/
public function __construct(
callable $nextHandler,
$headerName = 'X-GUZZLE-EFFECTIVE-URL'
) {
$this->nextHandler = $nextHandler;
$this->headerName = $headerName;
}
/**
* Inject effective-url header into response.
*
* @param RequestInterface $request
* @param array $options
*
* @return RequestInterface
*/
public function __invoke(RequestInterface $request, array $options)
{
$fn = $this->nextHandler;
return $fn($request, $options)->then(function (ResponseInterface $response) use ($request, $options) {
return $response->withAddedHeader($this->headerName, $request->getUri()->__toString());
});
}
/**
* Prepare a middleware closure to be used with HandlerStack
*
* @param string $headerName The header name to use for storing effective url
*
* @return \Closure
*/
public static function middleware($headerName = 'X-GUZZLE-EFFECTIVE-URL')
{
return function (callable $handler) use (&$headerName) {
return new static($handler, $headerName);
};
}
}
@addshore
Copy link

@Thinkscape Have you ever thought of turning this into something that can easily be installed using composer? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment