如何防止拦截的 Guzzle 3 请求生成 DNS 请求?
How to prevent an intercepted Guzzle 3 request from generating DNS requests?
我正在使用 Goutte 1.0.6(最新使用 Guzzle 3)构建网络抓取工具。为了进行测试,我想加载一个 HTTP 响应并提供它,而不是一个真正的 cURL 响应,这大部分工作正常。目前用例是单元测试,但我希望我也想将其用于生产缓存。
有趣的是,我注意到有时如果我与网络断开连接,我的单元测试就会变慢。我用 Wireshark 做了一些挖掘,发现我对 http://example.com/something
的调用正在生成 DNS 请求,即使它们是不必要的。
这是我的 Guzzle 插件的相关片段,用于提供虚假响应。相关位是捕获的 request.before_send
事件,如果在 Propel table:
中找到缓存项,则请求在末尾填充了响应。
class SavedPageLoaderPlugin extends HttpPluginBase
{
public static function getSubscribedEvents()
{
return array(
'request.before_send' => 'onRequestBeforeSend',
);
}
/**
* Handles a Guzzle event before an HTTP op is attempted
*
* @param \Guzzle\Common\Event $event
* @throws \WebScraper\PauseException
*/
public function onRequestBeforeSend(Event $event)
{
// @var $request Guzzle\Http\Message\Response
$request = $event['request'];
// Decide if we are caching for this run
if (!$this->isLoadEnabled())
{
return;
}
// Decide if we have a URL for this request
$url = $request->getUrl();
$httpPage = HttpPageQuery::create()->
filterByUrl($url)->
findOne();
if (!$httpPage)
{
return;
}
// Set a notification message for all subscribers, then set response
$this->setContainerMessage(self::MESSAGE_USES_SAVED_PAGE);
$response = new Response(
200,
$this->convertHeadersIntoKeyedArray($httpPage->getHeaders()),
$httpPage->getBody()
);
$request->setResponse($response);
}
总而言之,代码本身可以正常工作。 Wireshark 没有显示通过端口 80 获取数据的实际尝试,也没有与 example.com 无法提供我要求的文档相关的失败异常(例如 404)。所以,我的假回复似乎没问题。
有什么方法可以防止 Guzzle 进行这些毫无意义的 DNS 调用?我确实考虑过使用 MockPlugin,但当时我不确定该怎么做,现在也不确定这是否会解决这个遗留问题。
(我更喜欢在插件中执行 faking/mocking,所以虽然我使用 MockPlugin
没问题,但我想在其中进行拦截,而不是按照文档。我想我可以扩展它,也许?)
可能我需要转移到更高版本的 Guzzle,如果这是唯一的方法,那就这样吧。我在一个旧项目中,当时最新的 Goutte 使用 Guzzle 3。我打算升级,但如果可能的话,我宁愿稍后再升级,因为我当前的版本可以满足我的所有需求。
Post 脚本:我突然想到 DNS 调用可能来自 Goutte 而不是 Guzzle。我不确定如何进行调试,至少部分原因是 Composer 将 Goutte 作为 .phar
文件获取。像 xdebug
这样的调试器在这里是否有用,可以查看网络调用的原因和位置?
啊哈:这既不是 Guzzle 也不是 Goutte。在我的代码的其他地方,为了 HTTP 日志记录,我拦截了 request.success
事件。这里我调用gethostbyname()
,其目的是明确地进行DNS查找。
现在已禁用,"mysterious" DNS 调用已消失。
我正在使用 Goutte 1.0.6(最新使用 Guzzle 3)构建网络抓取工具。为了进行测试,我想加载一个 HTTP 响应并提供它,而不是一个真正的 cURL 响应,这大部分工作正常。目前用例是单元测试,但我希望我也想将其用于生产缓存。
有趣的是,我注意到有时如果我与网络断开连接,我的单元测试就会变慢。我用 Wireshark 做了一些挖掘,发现我对 http://example.com/something
的调用正在生成 DNS 请求,即使它们是不必要的。
这是我的 Guzzle 插件的相关片段,用于提供虚假响应。相关位是捕获的 request.before_send
事件,如果在 Propel table:
class SavedPageLoaderPlugin extends HttpPluginBase
{
public static function getSubscribedEvents()
{
return array(
'request.before_send' => 'onRequestBeforeSend',
);
}
/**
* Handles a Guzzle event before an HTTP op is attempted
*
* @param \Guzzle\Common\Event $event
* @throws \WebScraper\PauseException
*/
public function onRequestBeforeSend(Event $event)
{
// @var $request Guzzle\Http\Message\Response
$request = $event['request'];
// Decide if we are caching for this run
if (!$this->isLoadEnabled())
{
return;
}
// Decide if we have a URL for this request
$url = $request->getUrl();
$httpPage = HttpPageQuery::create()->
filterByUrl($url)->
findOne();
if (!$httpPage)
{
return;
}
// Set a notification message for all subscribers, then set response
$this->setContainerMessage(self::MESSAGE_USES_SAVED_PAGE);
$response = new Response(
200,
$this->convertHeadersIntoKeyedArray($httpPage->getHeaders()),
$httpPage->getBody()
);
$request->setResponse($response);
}
总而言之,代码本身可以正常工作。 Wireshark 没有显示通过端口 80 获取数据的实际尝试,也没有与 example.com 无法提供我要求的文档相关的失败异常(例如 404)。所以,我的假回复似乎没问题。
有什么方法可以防止 Guzzle 进行这些毫无意义的 DNS 调用?我确实考虑过使用 MockPlugin,但当时我不确定该怎么做,现在也不确定这是否会解决这个遗留问题。
(我更喜欢在插件中执行 faking/mocking,所以虽然我使用 MockPlugin
没问题,但我想在其中进行拦截,而不是按照文档。我想我可以扩展它,也许?)
可能我需要转移到更高版本的 Guzzle,如果这是唯一的方法,那就这样吧。我在一个旧项目中,当时最新的 Goutte 使用 Guzzle 3。我打算升级,但如果可能的话,我宁愿稍后再升级,因为我当前的版本可以满足我的所有需求。
Post 脚本:我突然想到 DNS 调用可能来自 Goutte 而不是 Guzzle。我不确定如何进行调试,至少部分原因是 Composer 将 Goutte 作为 .phar
文件获取。像 xdebug
这样的调试器在这里是否有用,可以查看网络调用的原因和位置?
啊哈:这既不是 Guzzle 也不是 Goutte。在我的代码的其他地方,为了 HTTP 日志记录,我拦截了 request.success
事件。这里我调用gethostbyname()
,其目的是明确地进行DNS查找。
现在已禁用,"mysterious" DNS 调用已消失。