ChatGPTに質問しながらLambda関数を作成する

# はじめに
今回、Lambda@Edge で利用する Lambda 関数を用意する必要があったのでそのコードを ChatGPT に書いてもらうことにしました。

https://openai.com/chatgpt/

# 構成イメージ
今回は CloudFront + S3 という一般的な構成をベースに導入します。
また、ベースの構成はすでに用意済みの状態で、そこに Lambda@Edge を追加する内容となります。
![スクリーンショット 2024-08-28 10.16.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82090/f434b3b4-bad4-ff54-7ac2-302db02f0383.png)


# 要件
CloudFront の場合だとデフォルトルートは `index.html` の補完を設定することができますが、
その他のパスでは補完がされません。
> 通常
> ○ https://cloudfronturl/ → https://cloudfronturl/index.html
> × https://cloudfronturl/test/ → https://cloudfronturl/test/index.html

今回はそう言った場合で `index.html` を補完するLambda@Edge を導入します。
> Lambda@Edge 導入
> ○ https://cloudfronturl/ → https://cloudfronturl/index.html
> ○ https://cloudfronturl/test/ → https://cloudfronturl/test/index.html

こんな感じです。

# 導入
以下、ChatGPT との全文になります。読んでいただくとわかりますがただ質問してるだけです。

## 質問（１回目）
> cloudfrontでデフォルトルート以外のパス配下でindex.htmlがなくてもindex.htmlを見るようなlambda@edgeのコードを教えてください。
言語はpythonでお願いします。

## ChatGPT レスポンス（１回目）
>以下は、CloudFrontでデフォルトルート以外のパス配下でも`index.html`をデフォルトで表示するLambda@Edgeのコード例です。言語はPythonです。
>
>このコードは、リクエストされたパスがファイルで終わっていない場合、そのパスに`index.html`を追加して、リクエストをリダイレクトする役割を果たします。
>
>```python
>import re
>from urllib.parse import urlparse
>
>def lambda_handler(event, context):
>    request = event['Records'][0]['cf']['request']
>    uri = request['uri']
>    
>    # パスの末尾がスラッシュで終わるか、またはファイル拡張子がない場合
>    if uri.endswith('/') or not re.search(r'\.\w+$', uri):
>        # `index.html`をパスに追加
>        request['uri'] = re.sub(r'/$', '', uri) + '/index.html'
>    
>    return request
>```
>
>### 説明:
>- **re.search(r'\.\w+$', uri)**: URIにファイル拡張子が含まれているかどうかをチェックします。含まれていない場合は、ディレクトリと見なされます。
>- **re.sub(r'/$', '', uri)**: パスの末尾のスラッシュを削除します。
>
>### 利用方法:
>1. Lambda関数を作成し、このコードをペーストします。
>2. CloudFrontディストリビューションのビヘイビアで、`Origin Request` または `Viewer Request` トリガーにこのLambda@Edge関数を関連付けます。
>
>これにより、ユーザーがCloudFrontを介してアクセスする際に、デフォルトルート以外のパスでも`index.html`をデフォルトで表示することができます。

python コードだけでなく説明や利用方法まで教えてくれました。
ただ、今回は `re` モジュールがデフォルトでサポートされているのかが気になりました。


## 質問（２回目）
ということで聞いてみます。
>reはlambdaのデフォルトでサポートされてますか？

## ChatGPT レスポンス（２回目）
> いいえ、Lambda@Edgeの環境では標準ライブラリの`re`（正規表現モジュール）はデフォルトでサポートされています。したがって、`re`モジュールをインポートして使用することができます。
>
>ただし、Lambda@Edgeでは特定のライブラリがサポートされていないことがあるため、外部のパッケージが必要な場合は注意が必要です。しかし、`re`モジュールはPythonの標準ライブラリの一部なので、特別な設定なしに利用可能です。
>
> もし正規表現を使用したくない場合は、URIのチェックを別の方法で行うことも可能です。

「いいえ」と言いつつ「サポートされています」という返事です。その後の内容を読んでも結局サポートされているのかがよく分かりません。


## 質問（３回目）
ということで改めて質問してみます。

>lambdaではサポートされていないけど、lambda@edgeではサポートされているということですか？


## ChatGPT レスポンス（３回目）

> `re`モジュールは、Pythonの標準ライブラリの一部であり、LambdaとLambda@Edgeの両方でサポートされています。したがって、Lambda@Edge専用でサポートされているわけではなく、どちらの環境でも利用可能です。
>
> 両方の環境で標準ライブラリとして提供されているため、追加の設定やインストールなしで`re`モジュールを使うことができます。
>
> もし、Lambda関数で`re`モジュールを利用する際に問題が発生した場合は、それは別の要因が原因かもしれませんが、一般的に`re`モジュールは問題なく動作するはずです。

結局サポートされているので大丈夫ということですね。


## 質問（４回目）
その後、マネジメントコンソールで Lambda 関数を作成し Lambda@Edge へデプロイを行おうとしたところ、以下のエラーが表示されました。
![スクリーンショット 2024-08-28 10.34.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82090/dcbd3707-2a52-846d-89d9-5872a894b680.png)
これについても聞いてみます。
> 以下のエラーの対応について教えてください。
関数の実行ロールは、edgelambda.amazonaws.com サービスプリンシパルによって引き受け可能である必要があります。

## ChatGPT レスポンス（４回目）
> このエラーは、Lambda@Edge関数に関連付けられたIAMロールが、CloudFrontでLambda@Edge関数を実行するために必要な権限を持っていないことを示しています。具体的には、IAMロールが`edgelambda.amazonaws.com`というサービスプリンシパルによって引き受けられるように設定されていないことが原因です。
>
> この問題を解決するには、以下の手順に従ってIAMロールの設定を修正します。
>
> ### 手順 1: IAMロールの修正
> 1. **AWSマネジメントコンソール**にログインします。
> 2. **IAMコンソール**に移動します。
> 3. Lambda@Edge関数に関連付けられているIAMロールを選択します。
> 4. **信頼関係**タブをクリックします。
> 5. **ポリシードキュメントの編集**をクリックし、以下の内容が含まれていることを確認または追加します。
>
>```json
>{
>  "Version": "2012-10-17",
>  "Statement": [
>    {
>      "Effect": "Allow",
>      "Principal": {
>        "Service": "edgelambda.amazonaws.com"
>      },
>      "Action": "sts:AssumeRole"
>    }
>  ]
>}
>```
>
> このポリシーは、`edgelambda.amazonaws.com`サービスプリンシパルに、このIAMロールを引き受ける権限を付与します。
>
>### 手順 2: 変更の保存
>- ポリシードキュメントの変更を保存し、IAMロールを更新します。
>
>### 手順 3: Lambda関数の再デプロイ
>- Lambda@Edge関数を再度デプロイし、CloudFrontディストリビューションに関連付けます。
>
>この手順を実施することで、CloudFrontでLambda@Edge関数を正常に実行できるようになります。

信頼関係で Lambda@Edge に許可されていないのが原因ということです。
また、対応手順についても答えてくれました。


## 質問（５回目）
無事に解決できたのですが、さっきの質問でちょっと疑問があったので追加で質問してみました。
> Origin Request とViewer Request の違いは何ですか？

## ChatGPT レスポンス（５回目）
>`Origin Request` と `Viewer Request` は、CloudFrontがリクエストを処理する際にトリガーされるタイミングの違いを示す用語です。それぞれの違いを理解することは、Lambda@Edge関数をどのタイミングで実行させるかを決める上で重要です。
>
>### Viewer Request
>- **タイミング**: エンドユーザー（ビューワー）からCloudFrontにリクエストが届いたときにトリガーされます。
>- **用途**: リクエスト内容を変更したり、ユーザーのリクエストに基づいてカスタム処理を実行する際に使用されます。例えば、認証やリクエストのリダイレクト、カスタムヘッダーの追加などができます。
>- **典型的なシナリオ**:
>    - ユーザーからのリクエストを特定の言語にリダイレクトする。
>    - 認証トークンの検証を行い、アクセスを許可するかを決定する。
>
>### Origin Request
>- **タイミング**: CloudFrontがリクエストをオリジン（例えば、S3バケットやウェブサーバー）に送信する前にトリガーされます。
>- **用途**: オリジンに対して送信されるリクエストを変更したり、オリジンに送る前にカスタム処理を実行する際に使用されます。例えば、オリジンに送るリクエストのURIを変更したり、カスタムヘッダーを追加することができます。
>- **典型的なシナリオ**:
>    - 特定のパスのリクエストを別のオリジンにルーティングする。
>    - リクエストURIを変更して、動的なコンテンツを配信する。
>
>### 主な違い
>- **Viewer Request** は、ユーザーからCloudFrontにリクエストが来た瞬間に処理が開始され、リクエストがオリジンに到達する前に変更できます。
>- **Origin Request** は、CloudFrontがリクエストをオリジンに送る直前にトリガーされ、オリジンに送信するリクエスト内容を変更することができます。
>
>### まとめ
>- **Viewer Request**: ユーザーからのリクエストを初期処理するために使用されます。
>- **Origin Request**: オリジンにリクエストを送る前に、リクエストを最終的に変更するために使用されます。
>
>Lambda@Edge関数をどちらでトリガーするかは、実現したい機能によって選択します。例えば、リクエストを受けた瞬間に特定の処理を行いたい場合は`Viewer Request`を、オリジンに対してリクエストをカスタマイズしたい場合は`Origin Request`を選ぶとよいでしょう。

違いだけでなく用途など詳しく回答してくれています。
とりあえず質問は以上で終了です。


# おわりに
ChatGPT を活用することで開発工数が大幅に削減できるなと感じました。
もっとプロンプトの内容がうまく書ければより効率よくコーディングなどができると思うのでもっと積極的に利用していこうと思います。