LoginSignup
4
3

More than 3 years have passed since last update.

ブラウザからの先読みリクエスト(Prefetch)はどうやって判定すべきか

Last updated at Posted at 2020-03-04

TL;DR

先読みリクエスト(プリフェッチ, Prefetch)はcssだけじゃなくて他のURLにも飛ぶケースがある。
特定のエンドポイントに対して、

  • ユーザーのアクションに起因するGETリクエストの件数をより正確に知りたい
  • 割と重い処理なので余計なリクエストはなるべく処理したくない

上記ニーズがある場合プリフェッチ対策をした方が良い。

経緯

あるWebシステムを開発中、テストサーバーに対してどう考えても意図しないGETリクエストがログに入ってきたため、原因について考えた。
調べたところ、ブラウザバーに何かを入力したりした時にブラウザが先読み(プリフェッチ)処理としてGETリクエストを飛ばすことがあるらしく、そのリクエストに関してはヘッダーに固有の値が設定されるため、それぞれのブラウザの仕様に対して検知処理を実装して対応した。

各ブラウザごとのプリフェッチを示すヘッダー

Chrome(Chromium)

Purpose: prefetch または X-Purpose:prefetch
https://www.chromestatus.com/feature/6247959677108224
https://bugs.chromium.org/p/chromium/issues/detail?id=86175#c65

Firefox

X-Moz: prefetch
https://developer.mozilla.org/ja/docs/Web/HTTP/Link_prefetching_FAQ

Safari

X-Purpose: preview
※ 使ってないという情報もあり

クローラーやネイティブアプリからのプリフェッチに関して

アトリビューション分析にBotやクローラー対策を行うのはもちろんのことですが、その他にもSNSの広告フィードに対して掲載されたページが事前にBotがキャッシュする場合に、プリフェッチ機能が使われるようです。(thank you @fujitatakesh )
プリフェッチのしくみとFacebookでの利用方法を理解する | Facebook Businessヘルプセンター

広告がクリックされると、最初のページはFacebookのキャッシュから読み込まれます。

この場合を考えると、プリフェッチされたくないURLをSNS上での操作で制御できるケースもありますが、Facebook以外でも同様の仕様が取られている場合に、広告のアトリビューション分析をサーバーサイドのHTMLへのGETリクエストを基に計測するのでは不十分なケースがあると考えられるので、javascriptなり何なりでユーザーの起点で計測できるように考慮された設計になっている方が良いと思います。

実装例

import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;

public static boolean isPrefetchRequest(HttpServletRequest request) {
    return StringUtils.equalsAny(request.getHeader("purpose"), "Prefetch", "prefetch") ||
            StringUtils.equalsAny(request.getHeader("X-moz"), "Prefetch", "prefetch") ||
            StringUtils.equalsAny(request.getHeader("X-Purpose"), "Preview", "preview") ||
            StringUtils.equalsAny(request.getHeader("X-Purpose"), "Prefetch", "prefetch");
}

※ Javaの場合ヘッダーのキーを case insensitive に評価することと、値は小文字で来ているらしいけど保険を取る目的で大文字小文字を含めて評価しているため上記のような実装になっている→Link prefetching FAQ - HTTP | MDN

補足

  • 軽く調べた感じではブラウザごとにフワフワしてる仕様なので、変更が入る前提で経過観察する。
もちろん、このリクエストヘッダーはまったく標準化されておらず、将来のMozillaリリースで変更される可能性があります。
Chromeは「X-Purpose:prefetch」または「Purpose:prefetch」ヘッダーを使用します。
4
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3