> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tryprofound.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Amazon CloudFront のセットアップ

> Lambda@Edge を使わずに、1 つの CloudFront Function とオリジングループで AI アシスタントのトラフィックを Profound Dynamic Bot Rendering にルーティングします。

このガイドでは、既存の CloudFront ディストリビューションを Dynamic Bot Rendering に接続します。このセットアップでは、ビューワーリクエストに CloudFront Function を 1 つ追加し、対象となる AI アシスタントのページリクエストに対してオリジンを選択します。

このセットアップでは Lambda\@Edge を使用しません。この統合は、次の 2 つの特性によって成り立っています。

* ビューワーの `Host` 転送が無効になっている場合、CloudFront は `Host` ヘッダーと TLS の Server Name Indication(SNI)にカスタムオリジンのドメインを使用します。ステップ 3 の両方のポリシーで、この設定を維持してください。
* Profound の CloudFront エンドポイント自体が `cache-control: no-store` を返すため、Profound がすでにキャッシュしているコンテンツについて、CloudFront が古い 2 つ目のコピーを保存することはありません。

<Note>
  Profound にルーティングされたリクエストは、CloudFront エンドポイント `GET https://concierge.tryprofound.com/v1/concierge/cloudfront/{path}` を使用します。この URL を手動で組み立てる必要はありません。オリジンの **Origin path** 設定によってプレフィックスが付加され、リクエスト URI は変更されずにそのまま渡されます。
</Note>

## この設計の理由

以下のすべての内容は、2 つの CloudFront のルールに基づいています。

1. ビューワーリクエスト関数では、リクエストが一致するキャッシュビヘイビアを変更できません。CloudFront は関数の実行前にビヘイビアを選択し、URI を書き換えても再照合は行われません。そのため、アシスタントのトラフィックは、独自のキャッシュポリシーを持つ専用のビヘイビアではなく、人間のトラフィックと同じビヘイビアで処理されます。
2. ビューワーリクエスト関数ではオリジンを切り替えることができ、フェイルオーバー付きのリクエストごとのオリジングループを構築することもできます(`cf.createRequestOriginGroup`、ランタイム `cloudfront-js-2.0`)。

ここから、次の 2 つの帰結が導かれます。

* ルーティングは、ビヘイビアではなくオリジンを切り替えることで行われます。**Origin path** はオリジンごとの設定であるため、デフォルトオリジンへのフェイルオーバー時には、自動的にプレフィックスなしの元のパスが使用されます。パスの書き換えは不要です。
* アシスタントと人間のリクエストはビヘイビアのキャッシュポリシーを共有するため、マーカーヘッダーでキャッシュキーを分割する必要があります(ステップ 3)。これを行わないと、CloudFront が人間向けにキャッシュしたコピーをアシスタントに配信したり、その逆が起きたりする可能性があります。

## 前提条件

* 既存の CloudFront ディストリビューション

* CloudFront のディストリビューション、関数、キャッシュポリシーに対する AWS Identity and Access Management(IAM)の権限

* Dynamic Bot Rendering の API キー、登録済みのドメイン、有効な配信ポリシー、および既知の公開済みテストページ。[始める前に](/ja-jp/dynamic-bot-rendering/overview#before-you-start)を参照してください。

* パーソナライズされていない公開ページのみが対象です。サンプルでは `/`、`/pricing`、`/docs`、`/docs/getting-started` を許可しています。これらをレビュー済みの公開ページに置き換えてください。API、認証、アカウント、管理、フレームワークのリソースのパスは含めないでください。

* ロールバックに備えて、既存の関数の関連付け、オリジン、ポリシーを記録してください。既存のセキュリティ、認証、リライトのロジックは維持してください。組み合わせるためにルーティング設計の変更が必要な場合は、作業を中止し、別途レビューしてください。

* ファイアウォールのルール、ボットチャレンジ、オリジンの許可リストが、アシスタントのトラフィックと、Profound のオリジン/スクレイパーによる取得の両方を許可していることを確認してください。ループマーカーは、認証やファイアウォールをバイパスするためのものではありません。

## セットアップ

<Steps>
  <Step title="Profound のオリジンを作成する">
    **CloudFront → Distributions → 対象のディストリビューション → Origins → Create origin** を開きます。

    | 設定 | 値 |
    | - | - |
    | Origin domain | `concierge.tryprofound.com` |
    | Origin path | `/v1/concierge/cloudfront` |
    | Name | `Profound_Origin` |
    | Protocol | HTTPS only |

    カスタムオリジンヘッダーを 2 つ追加します。

    | ヘッダー | 値 |
    | - | - |
    | `x-concierge-api-key` | Dynamic Bot Rendering の API キー |
    | `x-concierge-host` | サイトの公開ホスト(例: `www.example.com`) |

    CloudFront はこのオリジンに転送する際、ビューワーが送信した同名のヘッダーを上書きするため、クライアントが API キーやホストを偽装することはできません。多層防御として、ステップ 2 の関数でもこれらのヘッダーを削除します。

    <Note>
      **このディストリビューションから複数のホスト名を配信していますか?** 静的な `x-concierge-host` は単一の公開ホストでしか機能せず、静的なオリジンヘッダーは関数で設定した値よりも優先されます。マルチドメインのディストリビューションでは、ここでこのカスタムヘッダーを省略し、以下の関数でマークされた行のコメントを外して、ステップ 3 で `x-concierge-host` をキャッシュキーに含めることで転送もされるようにしてください。転送するだけでは、ホストごとのキャッシュレスポンスは分離されません。複数のホストを有効にする前に、人間向けのレスポンスとフォールバックレスポンスについても、ホストの識別をレビューしてください。
    </Note>
  </Step>

  <Step title="ビューワーリクエスト関数を作成する">
    **CloudFront → Functions → Create function** を開きます。名前を `profound-bot-rendering` とし、ランタイムに `cloudfront-js-2.0` を選択します。オリジングループには 2.0 ランタイムが必要です。

    ```js theme={null}
    import cf from 'cloudfront';

    // Keep this list in sync with the supported assistants in the Profound docs.
    var BOT_RE = /duckassistbot|chatgpt-user|gemini-deep-research|perplexity-user|amzn-user|mistralai-user|claude-user|claude-code|codex/i;

    // Replace with reviewed public, non-personalized page paths.
    var PUBLIC_PATHS = ['/', '/pricing', '/docs', '/docs/getting-started'];
    var PUBLIC_HOSTS = ['www.example.com'];

    function handler(event) {
        var request = event.request;
        var headers = request.headers;

        // Never trust these from a client. The API key and host come from the
        // origin's custom headers; the route marker feeds the cache key, so a
        // spoofed value could pollute the assistant cache entry.
        delete headers['x-concierge-api-key'];
        delete headers['x-concierge-host'];
        delete headers['x-concierge-url'];
        delete headers['x-concierge-route'];

        // Loop protection: Profound stamps x-concierge-request on its own origin
        // fetches. Never route those back to Profound.
        if (request.method !== 'GET' || headers['x-concierge-request']) {
            return request;
        }

        // CloudFront exposes cookies separately from request.headers.
        if (headers.authorization || Object.keys(request.cookies || {}).length > 0) {
            return request;
        }

        var ua = headers['user-agent'] ? headers['user-agent'].value : '';

        var isAssistant = BOT_RE.test(ua);
        var isPublicPage = PUBLIC_PATHS.indexOf(request.uri) !== -1;
        var host = headers.host ? headers.host.value : '';

        if (!isAssistant || !isPublicPage || PUBLIC_HOSTS.indexOf(host) === -1) {
            return request;
        }

        // Split the cache key. This header is in the behavior's cache policy,
        // so assistant responses never collide with human cache entries.
        headers['x-concierge-route'] = { value: 'bot' };

        // Multi-domain distributions only (see Step 1): derive the host from
        // the viewer Host header instead of a static origin custom header.
        // headers['x-concierge-host'] = { value: headers.host.value };

        // Try Profound first; fall back to your own origin if Profound is down
        // or misconfigured. CloudFront accepts 400, 403, 404, 416, 429, 500,
        // 502, 503 and 504 as failover criteria. 401 is not allowed, so a 401
        // from a bad API key surfaces to the assistant instead of failing over.
        // 404 is deliberately omitted: Profound fails open internally and
        // returns your origin's own status, so a 404 is your real 404 and
        // retrying would double-fetch. 429 is also omitted and passes through.
        cf.createRequestOriginGroup({
            originIds: [
                { originId: 'Profound_Origin' },
                { originId: 'YOUR_DEFAULT_ORIGIN' }
            ],
            failoverCriteria: {
                statusCodes: [400, 403, 500, 502, 503, 504]
            }
        });

        return request;
    }
    ```

    `YOUR_DEFAULT_ORIGIN` をディストリビューションの既存のデフォルトオリジン ID に、`PUBLIC_HOSTS` をこのオリジンの登録済みホストに置き換えてから、**Publish** を選択します。静的なホストヘッダーを使用する場合は、その 1 つのホストのみを指定してください。公開パスの完全一致の許可リストは、サイトのルートと一致させておいてください。Cookie や認可ヘッダーを含むリクエストは既存のルーティングのまま処理され、関数がそれらを Profound に送ることはありません。

    この関数がルーティングするのは `GET` のみで、それ以外のメソッドはすべて既存のルーティングに戻ります。CloudFront のオリジングループは、`GET`、`HEAD`、`OPTIONS` のフェイルオーバーをサポートしています。設定した `503` の条件は接続失敗時のフェイルオーバーを、`504` はレスポンスタイムアウト時のフェイルオーバーを有効にします。デプロイ前に、プライマリオリジンの接続試行回数、接続タイムアウト、レスポンスタイムアウトについて、フォールバックリクエストの時間を残せる上限値を設定して記録してください。CloudFront のデフォルトでは、接続試行だけで 30 秒(10 秒 × 3 回)かかる場合があります。結果として生じる合計レイテンシーをテストし、フェイルオーバーが即座に行われると想定しないでください。[CloudFront のオリジンフェイルオーバー](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/high_availability_origin_failover.html)を参照してください。
  </Step>

  <Step title="キャッシュポリシーとオリジンリクエストポリシーを更新する">
    CloudFront は、ビヘイビアのポリシーに含まれていないビューワーヘッダーやクエリ文字列をすべて削除します。これは関数の判断にかかわらず、オリジンリクエストの前に行われます。ページを配信するビヘイビアには、次の 3 つの設定が必要です。

    **1. `x-concierge-route` をキャッシュキーのヘッダーに追加します。** AWS マネージドキャッシュポリシーは編集できません。ビヘイビアでマネージドポリシーを使用している場合は、まずすべての設定を新しいカスタムポリシーにコピーしてから、ヘッダーを追加してください。**Minimum TTL**(有効期間)は `0` のままにしてください。マルチドメイン構成では、信頼済みの `x-concierge-host` を転送するだけでなく、キャッシュの識別情報にも含めてください。ボットマーカーだけではホストを区別できません。

    **2. ページの内容が変わるクエリ文字列**(または「All」)をキャッシュキーに含めます。キャッシュキーのクエリ文字列はオリジンにも届きます。オリジンリクエストポリシーを使えば、キーに含めずに追加のクエリ文字列を転送できますが、その値によって内容が変わるレスポンスがキャッシュエントリーを共有してしまう可能性があります。どちらのポリシーにもクエリ文字列が含まれていない場合、CloudFront はそれを削除します。サポートする各バリアントについて、転送とキャッシュの識別の両方を確認してください。

    **3. オリジンリクエストポリシーでビューワーの `User-Agent` を転送します。** デフォルトでは、CloudFront はオリジンリクエストの `User-Agent` を `Amazon CloudFront` に置き換えます。そうなると、Profound はルーティングされたすべてのリクエストを不明なエージェントとして分類し、常にフェイルオープンするため、レンダリングが配信されることもスケジュールされることもありません。`User-Agent` と、必要に応じて `Accept` および `Accept-Language`(マルチドメインの場合は `x-concierge-host` も)を対象としたカスタムヘッダー許可リストを使用してください。必要な圧縮設定は維持してください。**AllViewer** は使用しないでください。ビューワーの `Host` 転送によってサービスのホスト名が上書きされ、オリジンのルーティングや TLS が機能しなくなる可能性があります。ビューワーの `Host`、`Cookie`、`Authorization` は、キャッシュポリシーとオリジンリクエストポリシーの両方から除外してください。キャッシュキーの値も転送されます。これらのポリシーは人間のトラフィックにも適用されます。既存のビヘイビアでこれらのヘッダーや Cookie が必要な場合は、変更する前に作業を中止し、互換性をレビューしてください。CloudFront は、[リクエストオリジングループ](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/helper-functions-origin-modification.html)で `hostHeader` と `sni` のオリジンごとの `originOverrides` について説明しています。別のホストを必要とするお客様のオリジンについては、その互換性を別途レビューする必要があります。このサンプルでは、オーバーライドの選択や追加は行いません。Profound のオリジンフェッチは閲覧者の認証情報を転送せず、公開済みページはセッションごとや言語ごとのバリアントではありません。

    <Warning>
      このセットアップでは、`User-Agent` をキャッシュキーではなくオリジンリクエストポリシーに追加します。オリジンリクエストポリシーはビヘイビア全体に適用されるため、CloudFront は人間のリクエストでもビューワーの `User-Agent` を転送するようになります。オリジンが `User-Agent` によって HTML を変えている場合(たとえば、モバイルとデスクトップで別々のマークアップを返す場合)に、対応するキャッシュキーのバリエーションがないと、CloudFront がキャッシュされた 1 つのバリアントを他の閲覧者に配信してしまう可能性があります。既存のキャッシュキーがオリジンのバリアントをすでに考慮していることを確認してください。ロケール、地域、その他のヘッダーに依存するコンテンツもレビューが必要です。キャッシュ設計の変更が必要な場合は、デプロイ前に作業を中止してください。生の `User-Agent` をキーにすると、キャッシュの再利用率が大幅に低下する可能性があります。
    </Warning>
  </Step>

  <Step title="関数をビヘイビアに関連付ける">
    **Behaviors → 対象のページビヘイビア → Edit** を開きます。ステップ 3 のキャッシュポリシーを設定し、**Function associations** で **Viewer request** に `profound-bot-rendering` CloudFront Function を設定します。既存のエッジロジックがないビヘイビアであれば、オリジンリクエストやオリジンレスポンスの関連付けは不要です。既存の関連付けは削除しないでください。この関数を関連付ける前に、既存のビューワーリクエストのロジックを統合して維持してください。設計上の判断が必要な場合は作業を中止してください。

    保存し、ディストリビューションのデプロイが完了するまで待ちます。
  </Step>

  <Step title="検証する">
    ```bash theme={null}
    curl -sD - -o /dev/null https://www.example.com/pricing -A 'chatgpt-user'
    ```

    HTTP ステータス、有効な `x-concierge-request-id`、想定どおりの `x-concierge-bot-kind` を確認します。既知の公開済みページでは、`x-concierge-cache: HIT` と想定どおりのレンダリング済みボディも必須です。通常のブラウザートラフィック、GET 以外のメソッド、除外パス、認証情報を含むリクエストについて、既存の動作どおりであることをテストしてください。

    CDN レベルのフェイルオーバーは、ステージング環境または分離されたディストリビューションでのみテストしてください。元のオリジン設定を記録し、到達不能なテスト用オリジンを設定して、キャッシュされていないアシスタントリクエストを繰り返します。設定したタイムアウト後に、`x-concierge-request-id` のないデフォルトオリジンのレスポンスが返されることを確認します。元の設定を復元し、反映されるまで待ちます。`401` ではフェイルオーバーは発生しませんが、設定した `400` と `403` のステータスでは発生するため、設定エラーが隠れてしまう可能性があります。キャッシュされたフォールバックレスポンスは、TTL が切れるまで残る場合があります。

    すべてのチェック項目とヘッダーの意味については、[検証とトラブルシューティング](/ja-jp/dynamic-bot-rendering/verify-and-troubleshoot)を参照してください。
  </Step>
</Steps>

## キャッシュ分割の動作

* 関数がクライアントから送られたマーカーを削除するため、人間のリクエストにマーカーが含まれることはありません。マーカーによって人間のエントリーとアシスタントのエントリーは分離されますが、クエリやヘッダーのポリシーを変更すると、人間のキャッシュヒット率に影響する場合があります。
* 対象となるアシスタントのリクエストには `x-concierge-route: bot` が付与され、独自のエントリーが作成されます。
* Profound のレスポンスは `cache-control: no-store` を設定するため、Minimum TTL が `0` であれば、アシスタント用のキーのエントリーに格納されるのは、ご自身のオリジンからのフェイルオーバーレスポンスのみです。これは正しいコンテンツであり、オリジン自身の TTL で期限切れになります。

<Accordion title="既知の課題: 復旧後もフェイルオーバーレスポンスが残る場合がある">
  Profound が完全に停止している間、フェイルオーバーしたオリジンのレスポンスが、TTL が切れるまでアシスタント用のキーのキャッシュに残る場合があり、復旧後にレンダリング済みコンテンツに戻るまでに遅延が生じます。

  既存の TTL において、この復旧の遅延が許容できるかどうかを確認してください。フォールバックレスポンスのキャッシュ方法を変更するには、別途設計レビューが必要です。このガイドでは、その動作を変更するためのエッジ関数は追加しません。
</Accordion>

## ロールバック

記録しておいたビューワーリクエストの関連付けと、このセットアップのために変更したポリシーを復元します。**No association** は、以前に関数がなかった場合にのみ使用してください。設定が反映されるのを待ってから、元のルーティングとキャッシュの動作を確認します。以前にキャッシュされたフォールバックレスポンスは、TTL が切れるか、通常の手順で無効化されるまで残る場合があります。
