技術検証：API Gatewayを使ってLambda関数からS3の静的ページにリダイレクトする方法

## はじめに
AWS Lambdaはサーバーレスコンピューティングを提供し、特定のイベントに応じてコードを実行できる柔軟なツールです。

この記事では、Lambda関数からS3バケットにホストされた静的ウェブページにリダイレクトする方法を解説します。

リダイレクトを使うことで、Lambda関数のコードをシンプルに保ちながら、S3の静的コンテンツを利用(表示)することが技術的にできました。

## 知識整理
まず、S3とLambdaの基本的な役割を整理していきます。

:::note
**Amazon S3 (Simple Storage Service):** 
ファイルや静的コンテンツ（HTML、CSS、JavaScriptなど）を保存し、ウェブホスティングの機能も提供します。静的なウェブサイトを簡単にデプロイできます。

**AWS Lambda:** 
イベントドリブン型のサーバーレスコンピューティングサービスで、インフラの管理なしにコードを実行することができます。Lambda関数はAPI Gatewayと連携して、ウェブリクエストのレスポンスをカスタマイズ可能です。
:::

リダイレクトのアプローチは、S3にホストされた静的ページのURLをLambdaが返し、そのURLに基づいてウェブページをユーザーに表示します。

**この方法は、S3の静的ウェブホスティングを利用するため、処理が非常にシンプルです。**

## 今回の検証手順
### S3バケットの作成

まず、AWSコンソールにログインし、S3サービスを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/13ff35ce-a2d9-2652-1057-1be9e9f001f2.png)

「バケットの作成」ボタンをクリックし、新しいバケットを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/880f36f4-3cd2-8d66-29f8-15c0f6522c8a.png)

ここでは、パブリックアクセス設定を有効にしてインターネットに公開します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/9624afee-758e-b3be-2490-931b686d4763.png)

### S3で静的ウェブホスティングを有効にする

バケットを選択し、「プロパティ」タブに移動して、「静的ウェブサイトホスティング」を見つけてクリックし、有効にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/3640533e-9054-e6ad-ccb4-542830072538.png)

「インデックスドキュメント」として、表示したいファイル名（通常は index.html）を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/fa27349e-b98b-d9db-2340-1a6796e3f473.png)

「オブジェクト」タブに移動し、静的ウェブサイトとして公開したいHTMLファイル（例：index.html）や他の必要なファイルをアップロードします。

ここでは、以下のHTMLファイルをアップロードしました。

```indx.html
<!doctype html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>テストサイト</title>
</head>
<body>
朝活お疲れ様～!
</body>
</html>
```

デフォルトでは、S3バケット内のオブジェクトは非公開なので、インターネット経由でアクセスできるようにバケットポリシーを設定します。

### バケットポリシーを設定して公開アクセスを許可

現在の状態では、発行された「オブジェクト URL」でアクセスすると、以下のようにアクセスが拒否されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/954fdec8-7181-fd83-171d-0515c5e4b981.png)

バケットを選択し、「アクセス許可」タブに移動し、「バケットポリシーを編集」をクリックして、以下のようなバケットポリシーを追加します。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::honda-20241019/*"
        }
    ]
}
```

これにより、全世界からの公開アクセスが許可されます。

:::note warn
your-bucket-name の部分を、実際に使用しているバケット名に置き換えてください。
:::

この設定により、シンプルなテストページに問題なくアクセスできることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/547b6103-6624-7d99-b06d-24f66486f6c9.png)

### Lambda関数の作成と設定

AWSコンソールでLambdaサービスを選択し、「関数の作成」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/accf20d5-a0bc-10a0-a640-4e7d9517a564.png)

「一から作成」を選び、関数名（例: redirect-to-s3）を入力してPythonを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/64b90d25-5c54-ea29-fb3c-d857e336bccb.png)


:::note alert
実行ロールは「新しいロールを作成」を選択し、適切な権限を設定します。
:::

以下のコードをLambda関数に入力します。このコードは、リクエストを受けるとS3の静的サイトURLにリダイレクトします。

```json
import json

def lambda_handler(event, context):
    return {
        'statusCode': 302,
        'headers': {
            'Location': 'https://your-s3-static-site.s3-website-region.amazonaws.com'
        },
        'body': json.dumps('Redirecting to S3 static site')
    }
```

このコードは、302ステータスコードを返し、指定したS3のURLにユーザーをリダイレクトします。

ちなみに、テスト実行すると、以下のようにログに記録され、Lambda関数がS3の静的サイトURLに正常にリダイレクトされていることが確認できました。

```test.log
Test Event Name
aaaa

Response
{
  "statusCode": 302,
  "headers": {
    "Location": "https://honda-20241019.s3.ap-northeast-1.amazonaws.com/index.html"
  },
  "body": "\"Redirecting to S3 static site\""
}

Function Logs
START RequestId: e9ae69c2-d82e-462a-8f38-f6b0758664f2 Version: $LATEST
END RequestId: e9ae69c2-d82e-462a-8f38-f6b0758664f2
REPORT RequestId: e9ae69c2-d82e-462a-8f38-f6b0758664f2	Duration: 1.98 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 32 MB	Init Duration: 87.85 ms
```

### API Gatewayとlambda関数の連携
Lambda関数をAPI Gatewayと統合することで、HTTPリクエストに応じてLambda関数を呼び出せるようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/04df3a40-c0df-9fe9-8a3d-3dfd56f55d57.png)

「ルートの作成」をクリックし、GETリクエスト用のルートを作成します（例: /static-page）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/d1e950ca-1922-b559-c788-026e682bcf6a.png)

ここでは、APIをデプロイするための個別設定可能な環境のステージとして、「dev」を作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/916986f2-c794-efa4-9b8a-67383bf040dd.png)

最後に設定内容に問題がないことを確認して、作成ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/7a1a3cbf-4e11-f2ff-da91-3386db038e2c.png)

Lambda関数のサービスページでも、以下のように先ほど作成した「API Gateway」がトリガーとして設定されていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/374dec85-3b13-a68d-a45f-1fa7f72e6915.png)

## 検証確認

作成したAPI Gatewayをdev環境にデプロイし、API GatewayのエンドポイントURLにブラウザからアクセスします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/895e21d6-3bda-8347-d3f6-c08acf53fe10.png)

私のAPI Gatewayのエンドポイントは以下の通りです。

```bash
https://r22dg2a8pe.execute-api.ap-northeast-1.amazonaws.com/dev/static-page
```

ブラウザでこのエンドポイントURLにアクセスします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/d6d36cd9-7458-86e9-090d-79544c8a0ff1.png)

API GatewayのエンドポイントURLにアクセスすると、以下のS3バケットのURLにリダイレクトされることが確認できました。

```bash
https://honda-20241019.s3.ap-northeast-1.amazonaws.com/index.html
```

ちょうどこの時間に朝活をしていたので、技術検証が間に合って良かったです（笑）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/e146d3d9-2e30-9c53-0a24-e74d6d5fe17a.png)

Lambda関数も正しく実行され、エラーなく終了しており、ログからも成功していることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/d345502a-a07f-266d-a522-c4afe61e49d9.png)

## まとめ

この記事では、AWS Lambdaを使用して、S3バケットにホストされた静的ウェブページへリダイレクトする方法を紹介しました。

S3の静的ウェブホスティングを活用し、Lambda関数のコードをシンプルに保ちながら効率的に処理できます。

Lambda関数の作成からAPI Gatewayとの連携までの手順を詳細に解説し、ブラウザからの動作確認も問題なく完了しました。

## 参考文献

https://dev.classmethod.jp/articles/serverless-mailform-s3-website-hosting/