cloud frontとlambda@edgeでUA判定をしてPCページとSPページを出し分けてみた

  • 2
    いいね
  • 0
    コメント

cloud frontとlambda@edgeでUA判定をしてPCページとSPページを出し分けてみた

Webサービスを構築する仕事がきたのですが、ビジネスロジックが不要なサービスだったので
できるだけカンタンに作ろうと思いサーバーレス構築に挑戦してみた際にやってみたレポートになります。

使ったAWSのサービス

  • cloud front
  • lambda
  • S3
  • Route53(ドメイン設定の話なので今回は特に登場させません)
  • ACM(SSL証明書の話なので今回は特に登場させません)
  • Cloud Watch(lambdaを利用したら自動でついてきた)

やったこと

  1. S3にHTMLを配置
  2. cloud frontとS3を紐付け
  3. ドメインにアクセスした際にどのHTMLを出すか設定(トップページの設定)
  4. lambda@edgeにUA判定処理を実装
  5. lambda@edgeとcloud frontの紐付け(トリガー設定)今回はViewerリクエストをトリガーに設定

ざっくり動くまででだいたい2〜3時間くらいでできました。

1〜3はいろいろなところに記事が落ちているのでlambdaのソースと引っかかったポイントを紹介します。

lambdaに実装したソース

'use strict';

const whitelist = [
  'android',
  'iphone',
  'ipad'
];

const isSpBrowser = (uas) => {
  if (uas && Array.isArray(uas) && uas.length > 0) {
    return uas.some(ua => whitelist.some(w => ua.value.toLowerCase().indexOf(w) !== -1));
  }
  return false;
};

// User-AgentからPC・SP判定を行ない描画ページを切り替える
exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    // console.log('headers.user-agent. = ' + headers['user-agent']);
    if (headers['user-agent']) {
        // URI整理
        // cloud frontにトップページとして設定したindex.htmlがURIに入ってくるので除去
        var uri = request.uri.slice(-10) === ('index.html') ? request.uri.slice(0, -10) : request.uri;
        uri = uri.slice(-1) === ('\/') ? uri : uri + '\/';
        console.log('headers[user-agent] = ' + headers['user-agent'][0].value);
        // URI判定
        // ファイル読み込みで呼び出された場合中断
        if(uri.match(/( \.png|\.css|\.js|\.jpeg|\.jpg|\.bmp|\.gif|\.pdf|\.svg|\.zip)/)) {
            callback(null, request);
            return;
        }
        // UA判定
        if (isSpBrowser(headers['user-agent'])) {
            uri = uri + 'SP用描画ファイル名'
        } else {
            uri = uri + 'PC用描画ファイル名'
        }
        // XXX 現状パラメータを渡すことができない
        // uri = param === '' ? uri : uri + '?' + param
        console.log('uri = ' + uri);
        request.uri = uri
        callback(null, request);
        return;
    }
    callback(null, request);
};

ポイント

  1. ログはCloud Watchに出力されるがアクセスされたcloud frontのリージョンに出力されたのでlambdaを配置しているリージョンではない
  2. クエリストリングは使えない(2017年8月現在)
  3. ドキュメントは基本英語版が正
  4. トリガー設定はlambda側からやるほうがらく
  5. 困ったら迷わず有料サポートを使う(結果そのほうが早いのでトータルでの費用が下がる)

最後に

イベントページなどの後ろにビジネスロジックがいらないサービスであればこの構成は結構おすすめできると思います。
インフラ作業部分(エンジニアが必要な作業分)は大体5人日程度で収まったのでその分デザインやプロモーションにコストがまわせるのも強みかと
※初回なのでこれくらいですが慣れればもっと短くなる予感