👻

WebサイトのRefererとは?CSRとSSRでの挙動の違いと対処法

2025/01/17に公開

こんにちは、フロントエンドエンジニアのてりーです。
React + TypeScriptを5年以上使い続け、派遣 → フリーランス → メガベンチャーとキャリアを積んできました。
詳しいキャリアや学習ロードマップについてはこちらからどうぞ!

てりーのこれまで
フリーランスからメガベンチャーへ

はじめに

Webアプリケーションを開発する中で、一度は耳にしたことがあるHTTPリクエストヘッダーの一つがReferer(リファラー)です。

このヘッダーは、リクエストが送信された際に「どのページからそのリクエストが発生したか」を示す情報を提供します。
しかし、SSR(サーバーサイドレンダリング)からCSR(クライアントサイドレンダリング)に切り替えた際に、このRefererの挙動が変わり、意図しない動作に遭遇することがあります。

本記事では、Refererの仕組みやその役割、SSRとCSRでの挙動の違い、そして問題に対処する方法について解説します。

Refererとは?

Refererの役割

RefererはHTTPリクエストヘッダーの一つで、現在のリクエストがどのページから発生したかをサーバーに伝える役割を持っています。以下のようなシナリオで使用されます。

  • アクセス解析やログ記録
  • 外部リンクのクリック元を特定
  • セキュリティ(CSRFトークンの検証など)

例えば、ユーザーがページAからページBに遷移した場合、ページBのサーバーに送信されるリクエストヘッダーには、ページAのURLがRefererとして含まれます。

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Referer

Refererの仕様

Refererはブラウザの挙動や設定、そしてページのプロトコル(HTTP/HTTPS)やCSP(Content Security Policy)によって影響を受ける可能性があります。

  • セキュリティ向上のため、HTTPSページからHTTPページへのリクエストではRefererが省略されることがあります
  • 同一オリジン間でのみ送信される設定も可能です

参考記事
https://qiita.com/c0ridrew/items/7f2c9dad12543fa2662f

SSRとCSRでのReferer挙動の違い

SSRでのReferer

SSRでは、リクエストがサーバー上で生成されるため、サーバーが直接遷移前のページのURL(Referer)を取得できます。
ユーザーがページAからページBに遷移した場合、サーバーはページAのURLを正確に把握し、それをRefererヘッダーとしてリクエストに含めることが可能です。

CSRでのReferer

CSRでは、クライアントサイド(ブラウザ上)でレンダリングが行われます。
そのため、リクエストはJavaScriptを介して行われることが多く、この場合のRefererはリクエストを送信した時点の現在のページURLとなります。
つまり、遷移前のページURLをRefererとして取得できません。

以下のような現象が発生することがあります

  • SSRでは問題なかったRefererが、CSRでは現在のページURLに変わる
  • 明示的にリクエストパラメータにRefererを含めても、ブラウザが自動的に現在のページURLに書き換えてしまう

参考記事
https://zenn.dev/crebo_tech/articles/article-0013-20241102

なぜRefererが書き換わるのか?

Refererが書き換わる理由は、ブラウザのセキュリティポリシーに起因します。

セキュリティの観点

  • ブラウザは、ユーザーのプライバシー保護のためにRefererヘッダーを適宜変更することがあります
  • HTTPSからHTTPへの遷移や、クロスオリジンのリクエストでは、Refererが削除または短縮されることがあります

https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers

JavaScriptによる制御の限界

document.referrerを利用して遷移前のページURLを取得しようとした場合でも、ブラウザによって制限が加えられる場合があります。
このため、アプリケーション側で独自の方法を取る必要があります。

参考記事
https://risakodev.hatenablog.com/entry/2024/12/12/210036

CSRにおけるReferer問題の対処法

カスタムヘッダーの使用

CSR環境で正確な遷移前のページURLを取得するために、カスタムヘッダーを利用する方法があります。例えば、x-custom-refererというヘッダーを定義して、遷移前のページURLを明示的に送信する方法です。

カスタムヘッダーとは?

カスタムヘッダーは、開発者がアプリケーション固有の情報をHTTPリクエストに追加するための手段です。x-で始まる名前を付けることで、標準のHTTPヘッダーと区別します。

実装例

  1. フロントエンドで遷移前のページを取得
const previousPage = document.referrer;
fetch('/api/some-endpoint', {
  method: 'POST',
  headers: {
    'x-custom-referer': previousPage,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ data: 'someData' })
});
  1. サーバーでカスタムヘッダーを処理
app.post('/api/some-endpoint', (req, res) => {
  const customReferer = req.headers['x-custom-referer'];
  console.log('Custom Referer:', customReferer);
  res.status(200).send('Success');
});

カスタムヘッダーのやり取りに必要なCORS設定についてはこちらの記事にまとまっています!
https://zenn.dev/rescuenow/articles/bfc91492b19272

他の対策

  • セッションストレージやローカルストレージを使用して遷移前のページURLを保存する
    • ページ遷移時にsessionStorageにURLを格納し、次のリクエスト時に取得して送信する方法
  • リクエストパラメータでURLを明示的に渡す
    • ページ遷移時にクエリパラメータとして遷移前のページURLを付与する方法
    • ただし、URLに直接情報が記載されるため、セキュリティ面での考慮が必要です

実装時の注意点

  1. Refererヘッダーの取り扱いには十分注意すること
    • 不要な情報が漏洩しないよう、HTTPS通信やCSPの設定を活用する
  2. ブラウザ依存の挙動に注意する。
    • Chrome、Firefox、SafariなどのブラウザによってRefererの扱いが異なる場合があります
  3. パフォーマンスへの影響を考慮する
    • カスタムヘッダーを追加する際は、リクエスト全体のサイズや負荷を考慮する必要があります

まとめ

RefererはWeb開発において便利な情報を提供しますが、SSRとCSRでは挙動が異なるため、実装時には注意が必要です。
特に、CSR環境で遷移前のページURLを取得するには、カスタムヘッダーの利用やセッションストレージの活用などの工夫が必要です。

今後の開発では、Refererの仕様やブラウザのセキュリティポリシーを理解し、アプリケーションの要件に応じた設計を心がけましょう。

おすすめ記事

Discussion