web-dev-qa-db-ja.com

S3サブフォルダーのindex.htmlにリダイレクトします

ドメインexample.comを持っています。 example.comという名前のS3バケットがあり、index.htmlファイルが機能しています。次に、oldおよびnewという2つのサブフォルダーを作成します。それぞれに、単一ページアプリケーションの個別のバージョンが含まれています。 https://example.com/oldを要求すると(ブラウザーのアドレスバーに要求を入力するときにindex.htmlを省略したい)、oldサブフォルダーのindex.htmlファイルが開き、https://example.com/newindex.htmlを開きます。これらのリダイレクトを行う最良の方法は何ですか? Route 53 example.com/old-> example.com/old/index.htmlに何かを設定する必要がありますか、それとももっと良い方法がありますか?

18
g3blv

プロジェクトに費用と複雑さを追加するラムダ関数は必要ありません。

次の回答は https://stevepapa.com/ から引用されています

https://stevepapa.com/my-great-new-post/は以下と同じように機能することが期待されます:https://stevepapa.com/my-great-new-post/index.html

これらをCloudfrontディストリビューションに流すための賢い小さな方法があり、Cloud Originがデフォルトで提示するものからソースOriginを変更する必要があります。

Originのソースを選択すると、CloudfrontはS3バケットのリストを表示します。 editing Origin

ドロップダウンリストに表示されるバケットからソースを設定する代わりに、S3設定ページからそのリソースの静的ウェブホスティングエンドポイントを取得し、手動でポップインする必要があります。 where the static hosting endpoint url is

CloudfrontディストリビューションOriginに静的ソースを使用するということは、そのディストリビューションへのすべてのリクエストがS3のルートオブジェクトルックアップを使用することを意味し、参照が通過するにつれて404レスポンスが消えるはずです。

重要:これを行った後、ブラウザーのキャッシュをクリアし、 cloudfrontディストリビューションのアイテムを無効化 します。そうしないと、行った変更がすぐに反映されません。

35
Marc Guiselin

だから昨夜もこの問題がありました。

問題は次のとおりです。Webサイトバケットとして構成されているS3が許容範囲であり、インデックスドキュメント設定が_index.html_に設定されている場合、これはルートで適用されます。つまり、_example.com_は実際に_example.com/index.html_であり、サブフォルダレベルでも適用されるため、_example.com/new_または_example.com/new/_の両方が_example.com/new/index.html_にリダイレクトされ、バケット内にオブジェクトが存在します。 (そうでない場合は、代わりにNoSuchKeyエラーが表示されます。)

ただし、HTTPSのように、自分でCloudFrontに「アップグレード」すると、この機能はなくなります。 CloudFrontは代わりにS3への明示的なAPI呼び出しを行うため、インデックスドキュメントの譲歩はトリガーされません。ルートに対しては機能しますが、サブフォルダに対しては機能しません。

RoutingRulesソリューションは、キーと完全に等しい(存在しない)ではなくKeyPrefixEqualsを指定すると、意図しない一致が発生するため、見た目がきれいではありません。

代わりに、CloudFrontがS3に対して行うリクエストを書き換えて適切なキー値を設定するLambda @ Edgeルールを実装しました。

こちらのLambdaドキュメントとA/Bテストの例から始めてください: https://docs.aws.Amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-examples.html#lambda-examples-general-examples

コードを次のように変更します。

_'use strict';

exports.handler = (event, context, callback) => {
    /*
     * Expand S3 request to have index.html if it ends in /
     */
    const request = event.Records[0].cf.request;
    if ((request.uri !== "/") /* Not the root object, which redirects properly */
        && (request.uri.endsWith("/") /* Folder with slash */
            || (request.uri.lastIndexOf(".") < request.uri.lastIndexOf("/")) /* Most likely a folder, it has no extension (heuristic) */
            )) {
        if (request.uri.endsWith("/"))
            request.uri = request.uri.concat("index.html");
        else
            request.uri = request.uri.concat("/index.html");
    }
    callback(null, request);
};
_

そして、それをCloudFrontディストリビューションに公開します。

5
jkingok

HTMLリダイレクトファイルでこれを実現するさらに簡単な方法があります。

  1. My-great-new-postという名前のプレーンファイルを作成します(名前が同じバケット内のフォルダーと競合しないことを心配しないでください)。

  2. そのファイルにメタリダイレクトコードを記述します(以下のコードを貼り付けました)

  3. ルートバケット(my-great-new-postフォルダーが配置される場所)にファイルをアップロードします

  4. 新しいファイルのメタデータを変更し、Content-Type:text/htmlを作成します

ここにファイルの内容を示します:

<!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="refresh" content="0; url=/my-great-new-post/index.html">
    </head>
    <body>
    </body>
    </html>
0
AliAx

リダイレクトルールの設定を試すことができます。これはテストされていないルールです。

<RoutingRules>
  <RoutingRule>
    <Condition>
      <KeyPrefixEquals>old</KeyPrefixEquals>
    </Condition>
    <Redirect>
      <ReplaceKeyWith>old/index.html</ReplaceKeyWith>
    </Redirect>
  </RoutingRule>
  <RoutingRule>
    <Condition>
      <KeyPrefixEquals>new</KeyPrefixEquals>
    </Condition>
    <Redirect>
      <ReplaceKeyWith>new/index.html</ReplaceKeyWith>
    </Redirect>
  </RoutingRule>
</RoutingRules>
  1. 静的なウェブサイトを配信するようにバケットを構成する
  2. CloudFront Distribution :バケットをOriginとして設定し、OriginPathを空のままにします(デフォルト:/
  3. Route53 レコードセットを作成し、 CloudFrontディストリビューションにリンクします

役立つチュートリアルが こちら にあります

質問:顧客がexample.comold/newなし)を入力するとどうなりますか?

編集:2.はオプションです。 Route53 RecordSetを静的ウェブサイトにリンクすることもできますbutCloudFrontを使用すると、httpsAWS Certificate Manager )。

0
MaiKaY