私のアプリケーションでは、LWPを使用して定期的にWebページをフェッチしています。2つの連続したフェッチの間にWebページが何らかの点で変更されたかどうかを確認する方法はありますか(明示的に比較する以外)?抽出して古い署名と比較して変更の可能性を確認できる、下位のプロトコル層で生成されている署名(CRCなど)はありますか?
2 に答える
2つの可能なアプローチがあります。1つは、ページのダイジェストを使用することです。
use strict;
use warnings;
use Digest::MD5 'md5_hex';
use LWP::UserAgent;
# fetch the page, etc.
my $digest = md5_hex $response->decoded_content;
if ( $digest ne $saved_digest ) {
# the page has changed.
}
別のオプションは、サーバーが要求されたリソースにHTTP ETagを提供する場合、HTTPETagを使用することです。If-None-Match
単に保存してから、後続のリクエストにフィールドを含めるようにリクエストヘッダーを設定できます。サーバーのETagが同じままの場合は、304 Not Modified
ステータスと空の応答本文が表示されます。それ以外の場合は、新しいページが表示されます。(および新しいETag。)RFC2616のエンティティタグを参照してください。
もちろん、サーバーが嘘をついていて、コンテンツが変更されていても同じETagを送信している可能性があります。あなたが見ない限り知る方法はありません。
RFCの落とし穴に注意して、If-Modified-Since
リクエストヘッダーを使用する必要があります。このヘッダーをリクエストとともに送信します。サーバーがそれをサポートし、コンテンツが新しいと判断した場合、サーバーはそれを送信します。最新バージョンを使用していると思われる場合は、304
メッセージ本文なしでを返します。
ただし、他の回答が指摘しているように、サーバーは真実を伝える必要がないため、コンテンツのダウンロードと自分自身のチェックに行き詰まることがあります。多くの開発者は、Webアプリで基本的なHTTPをサポートすることを考えたことがないため、多くの動的なものは常に新しいコンテンツを持っていると主張します。
LWPビットの場合、追加のヘッダーを使用して単一の要求を作成できます。
use HTTP::Request;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
my $request = HTTP::Request->new( GET => $url );
$r->header( 'If-Modified-Since' => $time );
$ua->request( $request );
すべてのリクエストに対して、リクエストハンドラを設定できます。
$ua->add_handler(
request_send => sub {
my($request, $ua, $h) = @_;
# ... look up time from local store
$r->header( 'If-Modified-Since' => $time );
}
);
ただし、ファイルを保存する場合は、LWPでこのほとんどを実行できmirror
ます。
$ua->mirror( $url, $filename )