如何防止拦截的 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 调用已消失。