44

我已经搜索了大约 2 个小时,但我无法弄清楚如何阅读最终响应 uri。

在以前版本的 PHP Guzzle中,您只需调用即可$response->getEffectiveUrl()获得它。

我希望在新版本中有类似的东西,所以最终代码如下所示:

$response = $httpClient->post('http://service.com/login', [
    'form_params' => [
        'user'   => $user,
        'padss'  => $pass,
    ]
]);

$url = $response->getEffectiveUrl();

但是在最新版本$response中现在是 aGuzzleHttp\Psr7\Response并且没有允许我检索 uri 的方法。

我在这里读到了重定向(http://guzzle.readthedocs.org/en/latest/quickstart.html#redirects),但它什么也没说

更新:6.1 版本现在允许您轻松地做到这一点:

https://stackoverflow.com/a/35443523/1811887

谢谢@YauheniPrakopchyk

4

7 回答 7

66

来自文档的 Guzzle 6.1 解决方案。

use GuzzleHttp\Client;
use GuzzleHttp\TransferStats;

$client = new Client;

$client->get('http://some.site.com', [
    'query'   => ['get' => 'params'],
    'on_stats' => function (TransferStats $stats) use (&$url) {
        $url = $stats->getEffectiveUri();
    }
])->getBody()->getContents();

echo $url; // http://some.site.com?get=params
于 2016-02-16T21:39:16.110 回答
22

track_redirects您可以通过设置参数检查您的请求的重定向:

$client = new \GuzzleHttp\Client(['allow_redirects' => ['track_redirects' => true]]);

$response = $client->request('GET', 'http://example.com');

var_dump($response->getHeader(\GuzzleHttp\RedirectMiddleware::HISTORY_HEADER));

如果有任何重定向,最后一个应该是您的有效网址,否则您的初始网址。

allow_redirects你可以在这里阅读更多关于http://docs.guzzlephp.org/en/latest/request-options.html#allow-redirects的信息。

于 2015-11-16T10:09:08.433 回答
9

我正在使用中间件来跟踪重定向链中的请求并保存最后一个。最后一个请求的 uri 就是你想要的。

试试这个代码:

$stack = \GuzzleHttp\HandlerStack::create();
$lastRequest = null;
$stack->push(\GuzzleHttp\Middleware::mapRequest(function (\Psr\Http\Message\RequestInterface $request) use(&$lastRequest) {
    $lastRequest = $request;
    return $request;
}));

$client = new Client([
    'handler' => $stack,
    \GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => true
]);

$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org/redirect-to?url=http://stackoverflow.com');
$response = $client->send($request);
var_dump($lastRequest->getUri()->__toString());

结果:

string(24) "http://stackoverflow.com"

类示例:

class EffectiveUrlMiddleware
{
    /**
     * @var \Psr\Http\Message\RequestInterface
     */
    private $lastRequest;

    /**
     * @param \Psr\Http\Message\RequestInterface $request
     *
     * @return \Psr\Http\Message\RequestInterface
     */
    public function __invoke(\Psr\Http\Message\RequestInterface $request)
    {
        $this->lastRequest = $request;
        return $request;
    }

    /**
     * @return \Psr\Http\Message\RequestInterface
     */
    public function getLastRequest()
    {
        return $this->lastRequest;
    }
}

$stack = \GuzzleHttp\HandlerStack::create();
$effectiveYrlMiddleware = new EffectiveUrlMiddleware();
$stack->push(\GuzzleHttp\Middleware::mapRequest($effectiveYrlMiddleware));

$client = new Client([
    'handler' => $stack,
    \GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => true
]);

$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org/redirect-to?url=http://stackoverflow.com');
$response = $client->send($request);
var_dump($effectiveYrlMiddleware->getLastRequest()->getUri()->__toString());
于 2015-07-08T08:14:11.050 回答
6

我认为最好使用响应头来存储这些信息。我写了一个简单的类,在X-GUZZLE-EFFECTIVE-URL标题中保存有效的 url:

https://gist.github.com/Thinkscape/43499cfafda1af8f606d

用法:

<?php
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');
于 2015-08-12T10:22:02.787 回答
5

接受的答案对我不起作用,但引导我前进:

$client = new \GuzzleHttp\Client();
$client->request('GET', $url, [
    'on_stats' => function (\GuzzleHttp\TransferStats $stats) {
        echo($stats->getHandlerStats()['redirect_url']);
    }
]);
于 2017-02-16T17:04:08.027 回答
0

对于 Guzzle 7

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface;

$onRedirect = function(
    RequestInterface $request,
    ResponseInterface $response,
    UriInterface $uri
) {
    echo 'Redirecting! ' . $request->getUri() . ' to ' . $uri . "\n";
};

$res = $client->request('GET', '/redirect/3', [
    'allow_redirects' => [
        'max'             => 10,        // allow at most 10 redirects.
        'strict'          => true,      // use "strict" RFC compliant redirects.
        'referer'         => true,      // add a Referer header
        'protocols'       => ['https'], // only allow https URLs
        'on_redirect'     => $onRedirect,
        'track_redirects' => true
    ]
]);

echo $res->getStatusCode();
// 200

echo $res->getHeaderLine('X-Guzzle-Redirect-History');
// http://first-redirect, http://second-redirect, etc...

echo $res->getHeaderLine('X-Guzzle-Redirect-Status-History');
// 301, 302, etc...
于 2021-10-25T20:16:44.093 回答
-1

我不是该主题的专家,但据我了解,有效 url 不是一般 HTTP 消息中定义的东西。我认为这与 Curl 相关,并且由于 Guzzle 可以使用任何 HTTP 处理程序来发送请求(请参阅此处),因此不一定存在信息。

于 2015-06-06T14:03:14.907 回答