web-dev-qa-db-ja.com

PHP / Curl:HEAD一部のサイトではリクエストに時間がかかる

URLのヘッドリクエストを実行し、応答ヘッダーを出力する単純なコードがあります。一部のサイトでは、完了までに長い時間がかかる場合があります。

たとえば、http://www.arstechnica.comには約2分かかります。同じ基本的なタスクを実行する別のWebサイトを使用して同じリクエストを試しましたが、すぐに戻ってきます。したがって、私が誤って設定したものが原因で、この遅延が発生しているはずです。

これが私が持っているコードです:

$ch = curl_init();
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt ($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);

// Only calling the head
curl_setopt($ch, CURLOPT_HEADER, true); // header will be at output
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); // HTTP request is 'HEAD'

$content = curl_exec ($ch);
curl_close ($ch);

同じ機能を実行するWebサイトへのリンクは次のとおりです。 http://www.seoconsultants.com/tools/headers.asp

上記のコードは、少なくとも私のサーバーでは、www.arstechnica.comを取得するのに2分かかりますが、上のリンクのサービスはすぐにそれを返します。

何が欠けていますか?

25
Ian

少し単純化してみてください:

print htmlentities(file_get_contents("http://www.arstechnica.com"));

上記は私のウェブサーバーに即座に出力されます。それがあなたのものではない場合、あなたのウェブホストがこれらの種類のリクエストを抑制するために適切な設定をしている可能性があります。

[〜#〜]編集[〜#〜]

上記は瞬時に行われるため、元のコードで this curl setting を設定してみてください。

curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true);

投稿したツールを使用して、http://www.arstechnica.comには、送信されたすべてのリクエストに対して301ヘッダーが送信されます。 cURLがこれを取得し、それに指定された新しい場所に従っていないため、スクリプトがハングする可能性があります。

2回目の編集

不思議なことに、上記と同じコードを試すと、私のWebサーバーもハングしました。私はこのコードを置き換えました:

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); // HTTP request is 'HEAD'

これとともに:

curl_setopt($ch, CURLOPT_NOBODY, true);

マニュアル はHEADリクエストを行うことをお勧めします。それは即座に機能するようになりました。

43

HEADはWebサーバーへの提案にすぎません。HEADの場合、正しいことを行うには、管理者。HEAD静的ファイルの場合、Apache(またはWebサーバーが何であれ)は、多くの場合、正しいことを実行します。HEAD dynamicページでは、ほとんどのセットアップのデフォルトはGETパスを実行し、すべての結果を収集し、コンテンツなしでヘッダーを送信するだけです。そのアプリケーションが3(またはそれ以上)のセットアップの場合、呼び出しは非常に高価になる可能性がありますHEADコンテキストは必要ありません。たとえば、Javaサーブレットでは、デフォルトでdoHead()はdoGet()を呼び出すだけです)。アプリケーションの場合、開発者はdoHead()を明示的に実装する必要があります(多くの場合、実装しません)。

フォーチュン100の会社から数百メガバイトの価格情報をダウンロードするためのアプリを見つけました。 HEADリクエストは、変更された日付が変更されるまでかなり定期的に実行することで、データの更新を確認します。このリクエストは、実際にバックエンドコールを行い、作成するたびにこのリストを生成します。バックエンドにギガバイトのデータが含まれ、複数の内部サーバー間でデータを転送するリクエストです。彼らは私たちにそれほど満足していませんでしたが、ユースケースを説明すると、すぐに代替ソリューションが思い付きました。HEADを実装した場合は、むしろそれを偽造するために彼らのウェブサーバーに依存するよりも、それは問題ではなかっただろう。

7
Trey

私のメモリが失敗しない場合、HEAD CURLのリクエストを実行すると、HTTPプロトコルのバージョンが1.0に変更されます(これは低速で、おそらくここで有罪の部分です)。

$ch = curl_init();
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt ($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);

// Only calling the head
curl_setopt($ch, CURLOPT_HEADER, true); // header will be at output
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); // HTTP request is 'HEAD'
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); // ADD THIS

$content = curl_exec ($ch);
curl_close ($ch);
4
Alix Axel

以下の関数を使用して、リダイレクトされたURLを見つけました。

$head = get_headers($url, 1);

2番目の引数は、キーを持つ配列を返します。たとえば以下はLocation値を示します。

$head["Location"]

http://php.net/manual/en/function.get-headers.php

3
San

この:

curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);

ヘッダーを取得しようとしていませんでした。
上記のように、データのページ読み込みに2分かからないようにしようとしました。
その不思議な小さなオプションにより、2秒に短縮されました。

0
Brad