AWS

静的ウェブサイトホスティングにおけるURL正規化のリダイレクトの実施

MMM Corporation
sho

はじめに

西藤です。

高可用性のある静的なウェブサイトホスティングを実現したい時には、Amazon S3とCloudFrontの組み合わせで構築できます。
ただし、そのような構成を取ったときにはたとえばApacheサーバーで構築した時のような .htaccessを使ったリダイレクト設定を行うことができません。

また、Amazon S3の静的ウェブサイトホスティングの機能の「リダイレクトルール」もありますが、正規表現によるルール設定をカバーしておらず、設定するルール数が膨れてしまいがちです。

たとえば、
example.com/test/index.htmlexample.com/test/

example.com/test2/index.htmlexample.com/test2/

のように "index.html" の有り、なしを揃えた正規化を行いたい場合は

  • /test/ にあるindex.htmlのURLをindex.htmlなしに
  • /test2/ にあるindex.htmlのURLをindex.htmlなしに

のような形で設定を追加していく必要が出てきます。

しかし、ウェブサイトのSEOを考える上ではリダイレクトルールは正規表現を使いながらなるべく
シンプルに実現したいものです。

そこで今回はLambda@edgeを使った形で、

  • 「末尾の "index.html" がない形でURL正規化」

というシナリオで検証したいと思います。

構成

S3 + CloudFrontでのウェブホスティングやその際にLambda@Edgeを使った場合の作り方の例などついては弊社ブログの

などにもございますので、割愛します。
これらの記事もぜひご覧ください。

Lambdaの内容

Lambda@Edgeの構築方法は省きましたので、早速コード例としましては以下の通り。

'use strict';
exports.handler = (event, context, callback) => {
  console.log("=====Redirection to the URL without index.html  =====");

  // Get request and request headers
  const request = event.Records[0].cf.request;
  const headers = request.headers;

  // If URL ends with index.html, redirect to URL without index.html.
  const isIndex = request.uri.endsWith('/index.html');
  if (isIndex) {
    console.log("=====Because the URL ends with index.html , redirect to the URL without index.html  =====");
    const withoutIndex = request.uri.replace(//index.html$/, '/');
    const response = {
      status: '301',
      statusDescription: 'Moved Permanently',
      headers: {
        location: [{
          key: 'Location',
          value: withoutIndex
        }]
      },
    };
    callback(null, response);
    console.log("=====Redirection to the URL without index.html has ended =====");
  }
  // Continue request processing if requested URL doesn't end with index.html
  callback(null, request);
};

具体的な流れとしては

  1. リクエスト時のURLの末尾が/index.htmlであるかを確認
  2. (それに合致した場合は)末尾の /index.html/に置き換えた形の Locationの値を持ったレスポンスヘッダーを生成して返す
  3. (合致していなかった場合は)リクエスト時のURLでそのままレスポンスを返す

という形になっています。
これを

Lambda@Edge設定

というように view-requestを起点にこのLambda関数が動作するようにすることで、URL正規化のリダイレクトを実現します。

(・・・蛇足ですが、初めは "index.html" を ""(空白)に置き換えようとして、うまくリダイレクトが効いてくれず、つまづいていました。
""(空白)にしてしまうと、レスポンスヘッダーのLocationの値がないことになってしまうことでうまく行かなかったようです。)

以上がURL正規化の準備です。次にS3上に構築したサイトの内容とアクセスした際の動作を見ていきます。

S3のウェブサイトの内容

構築したサイトの内容はこのような形です。

検証サイトコンテンツ内容

  • サイト直下にindex.html
  • aというディレクトリにindex.html
  • bというディレクトリにindex.html
  • bというディレクトリの中にあるcというディレクトリにindex.html

という具合です。

リダイレクトが効いていない場合

では、まずサンプルとして、

  • サイト直下のindex.html
  • bというディレクトリ内のcというディレクトリ内のindex.html

にリダイレクトが効いていない状態でアクセスします。

サイト直下のindex.html(リダイレクト無し)

index.htmlがある場合、ない場合どちらとも同じページが表示されています。

bというディレクトリ内のcというディレクトリ内のindex.html(リダイレクト無し)

こちらもindex.html有り無しどちらも表示されました。

リダイレクトが効いた場合

では、適用前の状況がわかったことで各パターンを試します。
見え方は変わらないので、結果だけを・・・。

サイト直下のindex.html

→ index.html無しの形でサイトドメイン名直下にリダイレクト

aというディレクトリのindex.html

→ index.html無しの形で aというディレクトリのパスにリダイレクト

bというディレクトリのindex.html

→ index.html無しの形で bというディレクトリのパスにリダイレクト

bというディレクトリの中にあるcというディレクトリにindex.html

→ index.html無しの形で cのディレクトリのパスにリダイレクト

どの階層においても希望通りリダイレクトが効いていました。

まとめ

以上のように、S3の「リダイレクトルール」の設定を各階層ごとに足し合わせて行かなくても、index.html有り無しのURL正規化が実現できました。

今回のようなindex.html有り無しのURL正規化のシナリオに限らず、さまざまなパターンのリダイレクトを実装する際の参考になれば幸いです。

AUTHOR
sho
sho
記事URLをコピーしました