2009-04-20 9 views
21

URLの先頭リクエストを行い、応答ヘッダーを出力する簡単なコードがあります。私はいくつかのサイトでこれが完了するまでに長い時間がかかることに気付きました。PHP/Curl:HEAD一部のサイトでリクエストが長時間かかる

例えば、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); 

はここで同じ機能したウェブサイトへのリンクです:上記http://www.seoconsultants.com/tools/headers.asp

コードを、少なくとも私のサーバー上で、取得するために2分かかりますwww.arstechnica.comを参照してください。ただし、上記のリンクのサービスですぐに返されます。

私には何が欠けていますか?

+1

欠けているもの_curl_応答体である、それはHEADリクエストヘッダーのみ(本文なし)を返すことを知らないので、それはより多くのデータを送信するために、サーバー用に待っています。カールは2分間待ってから放棄します。 – Jasen

答えて

41

それを少し単純化してみてください。

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

上記出力瞬時に私のウェブサーバ上で。それがあなたの上になければ、あなたのウェブホストは、これらの種類のリクエストを抑制するために何らかの設定をしている可能性があります。

EDIT

以上があなたのために瞬時に行われるため、元のコードにthis curl settingを設定してみてください:

curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true); 

あなたが投稿ツールを使用して、私はhttp://www.arstechnica.comが送られた301のヘッダを持っていることに気づきましたそれに送られたすべての要求に対して。 cURLがこれを取得していて、指定された新しいLocationに従わない可能性があります。その結果、スクリプトがハングする可能性があります。

SECOND EDIT:不思議十分

、あなたは上記の私のウェブサーバがあまりにもハング作っていたたのと同じコードをしようとしています。これにより

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

:道the manualある

curl_setopt($ch, CURLOPT_NOBODY, true); 

あなたはHEADリクエストを行うお勧めします私はこのコードを置き換えます。それは即座に動作させました。

+0

は即座にwww.arstechnica.comのhtmlコードを出力します。 – Ian

+0

変更はありませんが、残念です。 – Ian

+0

と私は最初のページの応答ヘッダーのみを取得しようとしていますが、それ以上の行は表示されません。 – Ian

2

私の記憶は、CURLでHEADリクエストをして私を失敗していない場合は(遅いと、ここではおそらく有罪一部である)1.0にHTTPプロトコルのバージョンを変更することを変更してみてください:あなたは持っている

$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); 
+0

デフォルトでHTTP 1.1を使用しているようですが、少なくとも私が最終的に受け取る応答に応じて表示されます。 HTTP/1.1 301 Moved Permanently いずれの場合も、その行は追加されません。 – Ian

6

HEADはWebサーバーへの示唆にすぎないことを覚えておいてください。 HEADが正しいことをするためには、管理者の側で明白な努力が必要なことがよくあります。あなたが静的なファイルを見せてくれるなら、Apache(またはあなたのWebサーバが何であれ)はしばしば適切なことをします。ダイナミックページを見ている場合、ほとんどの設定のデフォルトは、GETパスを実行し、すべての結果を収集し、コンテンツなしでヘッダーを返すだけです。そのアプリケーションが3つ(またはそれ以上)の層構成にある場合、その呼び出しはHEADコンテキストでは非常に高価で不必要になる可能性があります。たとえば、Javaサーブレットでは、デフォルトでdoHead()はdoGet()を呼び出します。アプリケーションに対して少しスマートなことをするには、開発者が明示的にdoHead()を実装しなければなりません。

数百メガバイトの価格情報をダウンロードするために使用されている幸運100会社のアプリがあります。変更された日付が変更されるまで、HEADリクエストを公平に定期的に実行して、そのデータの更新を確認します。この要求は実際にバックエンドでデータのギガバイトを必要とする要求を行うたびにこのリストを生成するためにバックエンド呼び出しを行い、いくつかの内部サーバー間でこの要求を繰り返すことが判明しました。彼らは私たちに非常に満足していませんでしたが、ユースケースについて説明したらすぐに代わりの解決策が出てきました。彼らがHEADを実装していたのであれば、Webサーバーに頼ってそれを偽造するのではなく、問題ではないでしょう。

0

この:

curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 

私はヘッダを取得しようとしていませんでした。
私は、いくつかのデータのページの読み込みを上記のように2分ほどしないようにしようとしました。
その魔法の小さなオプションは2秒に減少しました。

3

私はリダイレクトされたURLを見つけるために以下の関数を使用しました。

第2引数は、キーを持つ配列を返します。例えば、以下はLocationという値を与えます。

$head["Location"] 

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

+1

この関数はデフォルトでGETリクエストを使用しますが、PHPのstream_context関数を使用してHEADリクエストを使用するように設定することができます(該当する場合は、ページ全体を取得しないようにオーバーヘッドを減らすため)。一例がマニュアル入力で提供されています。 – Synexis

関連する問題