web-dev-qa-db-ja.com

ビヘイビアパスリダイレクトを使用した複数のCloudfrontオリジン

CloudfrontOriginサーバーとして機能している2つのS3バケットがあります。

example-bucket-1
example-bucket-2

両方のバケットの内容は、それらのバケットのルートにあります。 URLパターンに基づいてルーティングまたはリライトするようにCloudfrontディストリビューションを設定しようとしています。たとえば、これらのファイルでは

example-bucket-1/something.jpg
example-bucket-2/something-else.jpg

これらのURLがそれぞれのファイルを指すようにしたい

http://example.cloudfront.net/path1/something.jpg
http://example.cloudfront.net/path2/something-else.jpg

Path1とpath2のパターンに一致するキャッシュ動作を設定しようとしましたが、機能しません。パターンは実際にS3バケットに存在する必要がありますか?

16

更新:以下に示す元の回答は、2015年に作成された時点で正確であり、CloudFront自体の組み込みの動作に基づいて正しいものです。元々、リクエストパス全体がオリジンに存在する必要がありました。

URIが_/download/images/cat.png_であるが、オリジンが_/images/cat.png_のみを予期している場合、CloudFrontキャッシュ動作_/download/*_は、想定したことを実行しません-キャッシュ動作のパスパターンはマッチング専用です-一致したプレフィックスは削除されません。

CloudFront自体は、リクエストをオリジンに送信するときにブラウザーがリクエストしたパスから要素を削除する方法を提供していません。リクエストは、受信時に常に転送されるか、Originパスが指定されている場合は、先頭に余分な文字が含まれます。

ただし、2017年に Lambda @ Edge が導入されると、ダイナミクスが変化します。

Lambda @ Edgeを使用すると、CloudFrontフローでトリガーフックを宣言し、CloudFrontキャッシュがチェックされる前(ビューアリクエスト)またはキャッシュがチェックされた後(オリジンリクエスト)に、着信リクエストを検査および変更できる小さなJavascript関数を記述できます。これにより、リクエストURIのパスを書き換えることができます。たとえば、_/download/images/cat.png_のブラウザからのリクエストパスを変換して_/download_を削除すると、_/images/cat.png_のリクエストがS3(またはカスタムオリジン)に送信されます。

このオプションは、どのキャッシュ動作が実際にリクエストを処理するかを変更しません。これは常にブラウザによってリクエストされたパスに基づいているためです。ただし、実際にリクエストされたオブジェクトが他のパスにあるように、実行中のパスを変更できます。ブラウザによって要求されたものより。 Origin Requestトリガーで使用する場合、応答はブラウザーによって要求されたパスの下にキャッシュされるため、後続の応答を書き換える必要はなく(キャッシュから提供できます)、トリガーを起動する必要はありません。すべてのリクエストに対して。

Lambda @ Edge関数は、実装が非常に簡単です。これは、最初のパス要素が何であれ、それを削除する関数の例です。

_'use strict';

// lambda@Edge Origin Request trigger to remove the first path element
// compatible with either Node.js 6.10 or 8.10 Lambda runtime environment

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;           // extract the request object
    request.uri = request.uri.replace(/^\/[^\/]+\//,'/');  // modify the URI
    return callback(null, request);                        // return control to CloudFront
};
_

それでおしまい。 .replace(/^\/[^\/]+\//,'/')では、先頭の_/_に一致する正規表現とURIを照合し、その後に_/_であってはならない1つ以上の文字、さらに1つ_/_、および一致全体を単一の_/_に置き換える-したがって、パスはabcの正確な値に関係なく、_/abc/def/ghi/..._から_/def/ghi/..._に書き換えられます。これは、実行時間を大幅に増やすことなく、特定の要件に合わせてより複雑にすることができます...ただし、Lambda @ Edge関数は1つ以上のキャッシュ動作に関連付けられているため、処理する単一の関数は必要ありませんディストリビューションを通過するすべてのリクエスト-関連するキャッシュ動作のパスパターンに一致するリクエストのみ。

ブラウザーからのリクエストにプレフィックスを追加するだけでも、以下に示すようにOrigin Path設定を使用できますが、パスコンポーネントを削除または変更するには、上記のようにLambda @Edgeが必要です。


元の回答

はい、パターンはオリジンに存在する必要があります。

CloudFrontは、ネイティブで、特定のオリジンのパスに追加できますが、現在、パスの要素を削除する機能はありません(上記のようにLambda @ Edgeなしで) 。

ファイルがオリジンの_/secret/files/_にある場合は、「オリジンパス」を設定することで、リクエストをオリジンに送信する前にパスパターン_/files/*_を変換できます。

反対は真実ではありません。ファイルがオリジンの_/files_にあった場合、パスパターン_/download/files/*_からそれらのファイルを提供する組み込みの方法はありません。

追加(プレフィックス)はできますが、削除することはできません。

比較的簡単な回避策は、S3バケットと同じリージョンにあるEC2インスタンス上のリバースプロキシサーバーで、CloudFrontをプロキシに、プロキシをS3にポイントします。プロキシは、S3に向かう途中でHTTPリクエストを書き換え、結果のレスポンスをCloudFrontにストリーミングします。私はこのようなセットアップを使用していますが、そのパフォーマンスに失望することはありません。 (私が開発したリバースプロキシソフトウェアは、実際に複数のバケットを並列または直列にチェックし、受信した最初のエラー以外の応答をCloudFrontとリクエスターに返すことができます)。

または、カスタムオリジンとしてS3 Webサイトエンドポイントを使用している場合は、S3リダイレクトルーティングルールを使用してCloudFrontにリダイレクトを返し、未処理のプレフィックスを削除してブラウザーを送り返すことができます。これは、オブジェクトごとに追加のリクエストを意味し、レイテンシとコストがいくらか増加しますが、S3リダイレクトルールは、リクエストが実際にバケット内のファイルと一致しない場合にのみ起動するように設定できます。これは、ある階層構造から別の階層構造に移行する場合に役立ちます。

http://docs.aws.Amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html

http://docs.aws.Amazon.com/AmazonS3/latest/dev/HowDoIWebsiteConfiguration.html

34