APIを提供するALBでメンテナンスモード(503)を実現する(CORSに対応する)


APIを提供するALBでメンテナンスモード(503)を実現する(CORSに対応する)

この記事は

  • APIをALBを使って解決している
  • SPAとAPIのエンドポイントが違う(クロスオリジン)
  • SPA側でメンテナンスレスポンスをハンドルしている

という状況での解決方法になります。

はじめに

AWSのALBには固定レスポンスという機能があり、特定のステータスコードとbodyを固定で返却する事ができます。
コレを設定することで、アプリケーションがメンテナンスモードの時などに固定でメンテナンス画面を表示することが出来ます。

固定レスポンスの設定方法

ところが、SAP+APIのような構成のアプリケーションを使用している際、API側のALBで固定レスポンスを設定するとある問題が発生します。

SPA+APIモデルのアプリケーションで固定レスポンスが出来ない

ALBの固定レスポンスではメンテナンス中という旨のJSONを返却できます。しかし、以下のようにステータスコード、コンテンツタイプ、本文しか返却内容に設定することが出来ません。

元々APIとSPAのエンドポイントが違うアプリケーションの場合、アプリケーション側でCORSの対応をしていることが多々あると思われますが、ここでの固定レスポンスにCORS対応のヘッダーを含めることが出来ずSPA側でCORSのエラーが出てしまいます。

Lambdaを使って解決する

固定レスポンスでヘッダーの設定は無理そうなので、ALBからLambdaをターゲット指定し、そこでCORSヘッダー込みの503をレスポンスします。

1.とりあえずLambdaで関数を作ります

(ランタイムは好きなので良いですが、僕がフロントエンドエンジニアなので今回はNodeです)

2.関数を書きます。

pre-flightリクエスト時にも503を返すと面倒なのでpre-flightのときは204を返します。設定したいヘッダーを盛りに盛りましょう。


exports.handler = async (event) => {
  if(event.httpMethod === 'OPTIONS') {
    const response = {
      statusCode: 204,
      headers: {
        'Content-Type': 'application/json; charset=utf-8',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Headers': '*',
        'Access-Control-Allow-Credentials': 'true'
      },
      body: '',
    };
    return response;
  }
  const response = {
    statusCode: 503,
    headers: {
      'Content-Type': 'application/json; charset=utf-8',
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Headers': '*',
      'Access-Control-Allow-Credentials': 'true'
    },
    body: JSON.stringify({"message": "(サンプル)ただいまメンテナンス中です。ご迷惑をおかけいたしますが、よろしくおねがいいたします。メンテナンス期間:2020-7-1 19:00〜 2020-07-1 21:00"}),
  };
  return response;
};

保存します

3.ターゲットグループの作成

ALBから呼び出すために、Lambdaを起動するターゲットグループを作成します。

AWSのメニューからEC2を選択し、ロードバランシングのターゲットグループに移動します。

ターゲットグループを新規作成します
いい感じの名前をつけてさっきの関数を選択します。ついでにヘルスチェックも有効にしましょう。

作成したらALBにこのターゲットを設定します。

4.ALBにターゲットを設定する

ロードバランサーから、目的のロードバランサーを選択肢、リスナー>ルールの編集へアクセスします。

現状適用されているルールの一覧が出るので、ここに新規で作成します。

明らかに追加できそうなボタンがあるのでコレを押します。

任意の場所にルールを挿入したら以下のように設定します

今回はメンテナンスモードを想定しているのですべてのリクエストでこちらに反応するようにしています。

これで設定が完了です。このルールがトップのときはいかなるリクエストにも503をCORS付きで返却します。

あとがき

API Gateway...