Reputation: 13912
I've been researching a bit about Guzzle middleware and am a bit confused about some things.
My main goal: set up custom defined middleware to log requests and responses.
I'm planning on using composer require rtheunissen/guzzle-log-middleware
because it seems to make creating exactly the kind of middleware I'm interested in much easier -- all the other middleware seems cumbersome or doesn't do what I want, too much magic, to little control.
So anyway, what I'm confused about is this whole 'handler' business as it relates to middleware. All the code examples on the Guzzle website create a curl handler, like so:
$stack = new HandlerStack();
$stack->setHandler(new CurlHandler());
$stack->push($middleware);
$client = new Client(['handler' => $stack]);
Do I need to call $stack->setHandler()
? If I don't, will it just use the default handler? Is the default handler CurlHandler anyway? I just want guzzle to do what it normally does, and use that middleware package to just log the requests and responses, I don't want to tell Guzzle to use curl or anything else.
Upvotes: 1
Views: 2903
Reputation: 811
Handler is just a way of firing and handling responses of the requests.
Looking at the source code, it does not seem you can pass HandlerStack
with just the middlewares only, you need a handler too. However you can create a default HandlerStack with it's create
static method and then push your own middleware at the end. Like so:
$stack = HandlerStack::create();
$stack->push($middleware);
$client = new Client(['handler' => $stack]);
Here is the source code of how default HandlerStack gets created. 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());
And here is choose_handler()
function that determines which handler is best. 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 documentation can be a bit annoying when it comes to figuring out niche things like this, don't be afraid to look at their source code to understand things better in the future.
Upvotes: 3