Я использую Goutte 1.0.6 (последний, кто использует Guzzle 3) для создания веб-скребка. Для тестирования я хочу загрузить HTTP-ответ и использовать его вместо реального ответа cURL, и это в основном работает нормально. В настоящее время вариант использования — это модульное тестирование, но я ожидаю, что я хочу использовать это и для производственного кэширования.
Интересно, что я иногда замечал, что если я отключен от сети, мои модульные тесты замедляются. Я немного покопался в Wireshark и обнаружил, что мои звонки http://example.com/something
генерируют запросы DNS, даже если они не нужны.
Вот соответствующий фрагмент моего плагина Guzzle для предоставления поддельного ответа. Соответствующие биты являются захваченными request.before_send
событие и тот факт, что запрос заполняется в конце, если в таблице Propel найден элемент кэша:
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, и нет исключений по сбоям (например, 404), связанных с неспособностью example.com предоставить документы, которые я запрашиваю. Итак, мои фальшивые ответы кажутся нормальными.
Есть ли способ для меня, чтобы запретить Guzzle делать эти бессмысленные DNS-звонки? Я думал об использовании MockPlugin но я не был уверен, как это сделать в то время, и не сейчас, решит ли это эту оставшуюся проблему.
(Я предпочитаю делать подделку / издеваться внутри плагина, так что пока у меня нет проблем с использованием MockPlugin
Я хотел бы делать перехваты внутри него, а не снаружи, в соответствии с документами. Я думаю, я мог бы расширить это, возможно?)
Может быть, мне нужно перейти на более позднюю версию Guzzle, и если это единственный путь, пусть будет так. Я работаю над старым проектом, в котором последняя версия Goutte в то время использовала Guzzle 3. Я собираюсь обновиться, но лучше сделать это позже, если это возможно, так как мои текущие версии делают все, что я хочу.
Post Script: мне приходит в голову, что DNS-вызов мог исходить от Goutte, а не от Guzzle. Я не уверен, как отладить это, по крайней мере, отчасти потому, что Goutte выбирается Composer как .phar
файл. Может ли отладчик как xdebug
быть полезным здесь, чтобы увидеть, что делает сетевой вызов и где?
Ага: это не было ни Жра, ни Гутта. В другом месте моего кода я перехватываю request.success
событие для целей ведения журнала HTTP. Здесь я звоню gethostbyname()
, чья цель явно сделать поиск DNS.
Теперь это отключено, «таинственные» DNS-звонки исчезли.
Других решений пока нет …