何を作るか?
諸事情により、外部のURL短縮サービスを使えない場合のために、自前のURL短縮サービスを作ります。
このサービスは、以下の2つから構成されます。
- URL生成
- 入力された任意のURLに対して、短縮したURLを生成する
- 生成したURLを元のURLと共にAmazon S3に格納する
- URL取得
- 与えられた短縮URLを元にS3から元URLを取得する
- HTTPレスポンスでステータスコード301とともにLocationヘッダで元URLを返す
この記事では、Amazon APIGatewayを使ってURL取得の部分を実装します。
URL生成の部分はこちらの記事です
概要
構成はシンプルにAPIGatewayとS3、あとはそれに関わるIAMRoleのみです。
- クライアント(Webブラウザ)は、短縮URLの https: //API-ENDPOINT/hoge にアクセスする。
- APIGatewayはS3バケットにオブジェクト"hoge"を要求する。
- APIGatewayはS3から取得したオブジェクトの中のLocationプロパティをクライアントへのレスポンスのLocationヘッダに設定する。
- APIGatewayはStatusCodeを301としてクライアントにレスポンスを返す。
短縮したキーと、元のURLの対応付をS3オブジェクトのKeyとBody(の中のLocation)で持たせています。
API-ENDPOINTは、デフォルトではAPIGatewayのURL(RESTApi.execute-api.REGION.amazonaws.com/STAGE)になってしまい、短縮URLとしては長すぎるので、短めのドメインを取得して、APIGatewayにカスタムドメイン名を設定してください。
(この記事ではカスタムドメイン名の設定については触れません)
作成方法
CloudFormationのテンプレートを用意してあるので、まずはそれを実行します。
こちらからapp-geturl.yamlを取得して、CloudFormationで実行してください。
パラメータ無し、StackNameは任意で構いません。
動作確認
CloudFormationからS3バケットが作成されています。S3バケットに以下のファイルをhoge
という名前でアップロードしてください。
{
"Location": "https://www.google.com"
}
CloudFormationのOutputsに"Api"の値が出力されているので、{key}
の部分をhoge
に書き換えてWebブラウザからアクセスしてください。
https://www.google.com にリダイレクトされていれば成功です。
解説
APIGatewayで何を行っているかを説明します。CloudFormationで既に作成されているものを確認してください。
一言で言うと「APIGatewayをS3プロキシとして構成して、レスポンスヘッダにS3オブジェクトの内容からマッピングしている」ということになります。
まずは、APIGatewayをS3プロキシとして構成する方法ですが、APIGatewayのGETメソッドの統合リクエストを以下のように構成しています。
- パスパラメータとして
{key}
を定義し - S3へのリクエストパスが
バケット名/{key}
となるようにして - S3にGETメソッドを発行する
という感じです。こうすると、APIGatewayへのGETリクエストがそのままS3へと流れます。
詳細はこちら → Amazon S3 プロキシとして API を作成するhttps://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html
続いて、S3オブジェクトの内容をレスポンスにマッピングします。
まずは、APIGatewayからのレスポンスをWebブラウザがリダイレクトするように、APIGatewayのレスポンスを定義しています。
次に、APIGatewayのレスポンスに、S3から返ってきたオブジェクトの内容をマッピングしています。
- S3からのHTTPステータスが2xxだったらAPIGatewayが301を返す
- APIGatewayのレスポンスヘッダー
Location
に、S3からのレスポンスBodyのLocation
プロパティを設定する
まとめ
APIGatewayのS3プロキシとマッピング定義でプログラミングなしで、URL取得部分が実装できました。
あとは、S3バケットにオリジナルURLと短縮後のキーを格納する処理を実装するだけなので、任意のプログラムで実装していただければと思いますが、別記事でAWS Lambdaでの実装例を書く予定です。
おまけ
短縮URLに有効期限をつけたい場合、S3バケットのライフサイクルルールでオブジェクトを失効させることで、これもプログラミング無しで実現できます。