AWS
APIGateway

APIGatewayを使ってサーバーレスなURL短縮サービスを作る(URL取得編)

何を作るか?

諸事情により、外部の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のみです。

fig1

  1. クライアント(Webブラウザ)は、短縮URLの https: //API-ENDPOINT/hoge にアクセスする。
  2. APIGatewayはS3バケットにオブジェクト"hoge"を要求する。
  3. APIGatewayはS3から取得したオブジェクトの中のLocationプロパティをクライアントへのレスポンスのLocationヘッダに設定する。
  4. APIGatewayはStatusCodeを301としてクライアントにレスポンスを返す。

短縮したキーと、元のURLの対応付をS3オブジェクトのKeyとBody(の中のLocation)で持たせています。

API-ENDPOINTは、デフォルトではAPIGatewayのURL(RESTApi.execute-api.REGION.amazonaws.com/STAGE)になってしまい、短縮URLとしては長すぎるので、短めのドメインを取得して、APIGatewayにカスタムドメイン名を設定してください。
(この記事ではカスタムドメイン名の設定については触れません)

作成方法

CloudFormationのテンプレートを用意してあるので、まずはそれを実行します。

https://github.com/monamu/qiita-url-shorter

こちらからapp-geturl.yamlを取得して、CloudFormationで実行してください。
パラメータ無し、StackNameは任意で構いません。

動作確認

CloudFormationからS3バケットが作成されています。S3バケットに以下のファイルをhogeという名前でアップロードしてください。

hoge
{
  "Location": "https://www.google.com"
}

CloudFormationのOutputsに"Api"の値が出力されているので、{key}の部分をhogeに書き換えてWebブラウザからアクセスしてください。

https://docs.google.com/drawings/d/e/2PACX-1vSla7kQAbTIlDrC_0ubm9VUCxEnBFf1RliLs7gEwUp0DOSJ74jDQ3E-rbz_MVrbJPKEkSoV83r6trQw/pub?w=584&h=359

https://www.google.com にリダイレクトされていれば成功です。

解説

APIGatewayで何を行っているかを説明します。CloudFormationで既に作成されているものを確認してください。

一言で言うと「APIGatewayをS3プロキシとして構成して、レスポンスヘッダにS3オブジェクトの内容からマッピングしている」ということになります。

まずは、APIGatewayをS3プロキシとして構成する方法ですが、APIGatewayのGETメソッドの統合リクエストを以下のように構成しています。

  1. パスパラメータとして{key}を定義し
  2. S3へのリクエストパスがバケット名/{key}となるようにして
  3. 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バケットのライフサイクルルールでオブジェクトを失効させることで、これもプログラミング無しで実現できます。