PHP Guzzle - 如果我只是将它用于中间件,是否需要设置处理程序?

PHP Guzzle - do I need to set a handler if I'm just using it for middleware?

我一直在研究 Guzzle 中间件,但对某些事情有点困惑。

我的主要目标:设置自定义中间件来记录请求和响应。

我正计划使用 composer require rtheunissen/guzzle-log-middleware,因为它似乎使创建我感兴趣的那种中间件变得容易得多——所有其他中间件似乎都很麻烦或无法满足我的要求, 太多的魔法,很少的控制。

所以无论如何,我感到困惑的是整个 'handler' 与中间件相关的业务。 Guzzle 网站上的所有代码示例都创建了一个 curl 处理程序,如下所示:

$stack = new HandlerStack();
$stack->setHandler(new CurlHandler());
$stack->push($middleware);
$client = new Client(['handler' => $stack]);

我需要调用 $stack->setHandler() 吗? 如果不需要,它会使用默认处理程序吗?默认处理程序 CurlHandler 仍然存在吗?我只想让 guzzle 做它通常做的事情,并使用那个中间件包来记录请求和响应,我不想告诉 Guzzle 使用 curl 或其他任何东西。

处理程序只是触发和处理请求响应的一种方式。

查看源代码,似乎仅通过中间件无法传递 HandlerStack,您还需要一个处理程序。但是,您可以使用它的 create 静态方法创建一个默认的 HandlerStack,然后在最后推送您自己的中间件。像这样:

$stack = HandlerStack::create();
$stack->push($middleware);
$client = new Client(['handler' => $stack]);

这是如何创建默认 HandlerStack 的源代码。 Link

/**
 * Creates a default handler stack that can be used by clients.
 *
 * The returned handler will wrap the provided handler or use the most
 * appropriate default handler for your system. The returned HandlerStack has
 * support for cookies, redirects, HTTP error exceptions, and preparing a body
 * before sending.
 *
 * The returned handler stack can be passed to a client in the "handler"
 * option.
 *
 * @param callable $handler HTTP handler function to use with the stack. If no
 *                          handler is provided, the best handler for your
 *                          system will be utilized.
 *
 * @return HandlerStack
 */
public static function create(callable $handler = null)
{
    $stack = new self($handler ?: choose_handler());
    $stack->push(Middleware::httpErrors(), 'http_errors');
    $stack->push(Middleware::redirect(), 'allow_redirects');
    $stack->push(Middleware::cookies(), 'cookies');
    $stack->push(Middleware::prepareBody(), 'prepare_body');
    return $stack;
}


$stack = new self($handler ?: choose_handler());

这里是 choose_handler() 函数,用于确定最佳处理程序。 Link

/**
 * Chooses and creates a default handler to use based on the environment.
 *
 * The returned handler is not wrapped by any default middlewares.
 *
 * @throws \RuntimeException if no viable Handler is available.
 * @return callable Returns the best handler for the given system.
 */
function choose_handler()
{
    $handler = null;
    if (function_exists('curl_multi_exec') && function_exists('curl_exec')) {
        $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
    } elseif (function_exists('curl_exec')) {
        $handler = new CurlHandler();
    } elseif (function_exists('curl_multi_exec')) {
        $handler = new CurlMultiHandler();
    }
    if (ini_get('allow_url_fopen')) {
        $handler = $handler
            ? Proxy::wrapStreaming($handler, new StreamHandler())
            : new StreamHandler();
    } elseif (!$handler) {
        throw new \RuntimeException('GuzzleHttp requires cURL, the '
            . 'allow_url_fopen ini setting, or a custom HTTP handler.');
    }
    return $handler;
} 

Guzzle 文档在解决像这样的小众问题时可能会有点烦人,不要害怕查看他们的源代码以便将来更好地理解事情。