API Gateway と Lambdaを使ってサーバレスでいい感じのリダイレクト環境を作る

2017.03.16

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、岩本です。

さて、サイトリニューアルやシステムのリプレイスなどで、サイトのドメインやURL構成が変わる場合、
既存ドメイン・URLへのアクセスを、新環境へリダイレクトするケースが発生するかと思います。
そこで、リダイレクト用だけに維持し続けるのは勿体無いので、API Gateway と Lambda を使って
リダイレクト用の環境を構築して見ました。

やりたいこと

  • URL: https://old.hogehoge.com/user?name=xxxxx

に接続が来たら

  • URL: https://new.hogehoge.com/user/name/xxxxx

へと、リダイレクトを行いたい。

概要

  • APIGatewayで受け取ったURL Query Stringの値をLambdaに引き渡す
  • Lambdaでいい感じに変換
  • Lambdaで変換された出力を元に、APIGatewayで レスポンスコード(301)の出力と、Locationヘッダーに結果を付与する

Lambdaの用意

まず、URLの変換を行うためのLambdaを用意します。
仕組みは、入力された値をリダイレクト先のURLに付与して、Locationの値として出力します。

def lambda_handler (event, context):
name = event['name']
header_location = ("https://new.hogehoge.com/user/name/%s" % name)
result = {"Location": header_location}
return result

Lambdaのテスト

まずは、Lambdaが期待値通りの動きをすか確認するため、入力値は以下のように設定しテストを行いました。

  • 入力
{
"name": "hogehogetarou"
}

結果、出力は以下のようになっているので、成功です。

  • 出力
{
"Location": "https://new.hogehoge.com/user/name/hogehogetarou"
}

APIGatewayの用意

次に、API Gateway にてAPIを作成します。

  • リソースを作成
  • メソッドを作成
  • 今回は、ANYとして作成しました。
  • ANYメソッドからLambdaが呼び出されるように設定
  • 作成されたANYメソッドにて以下を設定

Method Request

Method RequestよりURL Query String Parametersname としてパラメータの追加をします。
追加するパラメータは以下の通りです。

{
"name": "$input.params('name')"
}

次に、パラメータを入力後Cachingにチエックをします。

Integration Request

Integration RequestよりBody Mapping Templates
application/jsonContent-Typeを追加します。
追加後application/jsonの内容を以下の通りとします。

{
"name": "$input.params('name')"
}

ここまでが、URLへのアクセスに基づくLambdaへの値の入力設定となります。

Method Response

次にLambdaで生成されたURLをヘッダーに含めるための設定をします。
Method Responseにて、HTTP Statusにリダイレクトのレスポンスコードとなる301を追加します。
次にResponse Headers for 301にて、HeaderLocationを追加します。

integration response

最後に、integration responseにて301を追加し200を消します。
追加した301Header MappingsMethod Responseにて追加されたLocationがあるので、
値にintegration.response.body.Locationを追加します。

以上で完了です。

TEST

最後にテストをします。

TESTに進みQuery Stringsnameという項目があるのでhogetarouなど適当な値を入れテストを実行します。

結果がこちらです。

Request: /?name=hoge
Status: 301
Latency: 111 ms
Response Body
  • Response Body
{
"Location": "https://new.hogehoge.com/user/name/hogetarou"
}
  • Response Headers
{"X-Amzn-Trace-Id":"Root=1-58ca0c80-b6fe8fb2f9708f96da189497","Content-Type":"application/json","Location":"https://new.hogehoge.com/user/name/hogetarou"}
  • リクエストに対し、302のエラーコードが帰っています。
  • ヘッダーのLocationにきちんと生成されたURLが入っています。

ここまでできれば、今作成したResourcesを元にAPIを作成することで、完了です。

解説

入力

Method RequestURL Query String Parametersintegration responseBody Mapping Templatesに設定した、

"name": "$input.params('name')"

により、URLのQuery Stringの値がLambdaに引き渡されます。

出力

引き渡された値は、integration responseHeader Mappings Method Response に設定した
integration.response.body.xxxにて、ヘッダーに値が割り当てられます。
今回はLambdaでの出力値Locationつまりintegration.response.body.Locationと設定しました。

今日のわさび様<

お饅頭感がすごい。窓ガラス掃除しないとなぁ。

IMG_9836