【AWS】AWS Lambda Function URLsを検証！


## はじめに

この記事では「この前リリースされた機能って実際に動かすとどんな感じなんだろう」とか「もしかしたら内容次第では使えるかも」などAWSサービスの中でも特定の機能にフォーカスして検証していく記事です。主な内容としては実践したときのメモを中心に書きます。（忘れやすいことなど）
誤りなどがあれば書き直していく予定です。

今回はAWS Lambdaの機能として提供されたAWS Lambda Function URLs（以下、Function URLs）を検証してみます。

## この記事で伝えたいこと(Point)

- AWS Lambda Function URLsを使うとAPI Gatewayを使わずにLambdaの機能だけでAPIエンドポイントURLを作成できるよ
- AWS Lambda Function URLsの特色はどこかについて説明しているよ

## LambdaがURLを発行するようになったね

[AWS Lambda Function URLs の提供開始: 単一機能のマイクロサービス向けの組み込み HTTPS エンドポイント - Amazon Web Services ブログ](https://aws.amazon.com/jp/blogs/news/announcing-aws-lambda-function-urls-built-in-https-endpoints-for-single-function-microservices/)

もうみなさん使っていると思いますが、ご存知ない人もいるため、簡単に説明します。

## AWS Lambda Function URLs（Function URLs）とは

簡単に説明すると、AWSのサービスでAPIを作成する手段が増えたという話です。
URLでLambdaを開けるようになったとも言います。

今までWeb APIを作成しようと思ったときはAmazon API Gatewayを使う必要があります。
つまり、API GatewayでLambdaを実行するための入り口を作ります。

Function URLsがなかった場合は主に以下の方法でLambdaを実行できました。

- AWS CLIで実行
- AWS マネジメントコンソールで実行
- AWS SDK / AWS CDKで実行
- イベントをキャッチして実行（イベント駆動）

ただし、実行方法については開発スタイルによって実行手段が限られてくるため、上記の方法がすべて利用できるわけではありません。（役に立つわけではないという意味）

「APIを実行したい。けど、API Gatewayまで作る必要はないんだよなぁ」みたいな状態でもFunction URLsを使えば、LambdaだけでWeb APIを開発できます。

## 実際に使ってみよう

今回はFunction URLsを使ってLambdaにアクセスしてみます。

## Lambda関数でHello World

### Lambda関数を作る

まずは東京リージョンのAWSマネジメントコンソールからAWS Lambdaを検索してクリックします。

![Screenshot 2024-11-02 at 21.42.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/f2f496f8-6544-69aa-ce5a-9220ebb7fab2.png)

左メニューからFunctionsをクリックします。

![Screenshot 2024-11-02 at 21.43.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/c53b5f7f-5079-2e2b-69b1-bc32a1c1f919.png)

東京リージョンであることを確認した上で`Create function`をクリックします。

![Screenshot 2024-11-02 at 21.44.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/77c582fd-2d55-0691-4b6e-1b8c86dd2482.png)

`Author from scratch`を選択します。

![Screenshot 2024-11-02 at 21.47.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/8b643c31-6340-c63e-0a79-50959685288f.png)

`Basic information`を設定します。以下のとおりに設定します。

|項目|値|
|:---|:---|
|Function name|LineFuncUrls|
|Runtime|Python3.12|
|アーキテクチャ|x86_64|

![Screenshot 2024-11-02 at 21.47.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/cfc27b66-5132-9d71-38a8-15f03b31ea6f.png)

Invoke modelはデフォルトの設定で問題ありません。

![Screenshot 2024-11-02 at 21.48.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/3bc6f57e-6df0-4671-9b9d-866d427ed0d5.png)

Additional Configurationsを設定します。ここで`Function URLs`の設定があります。デフォルトでチェックが無効になっているため、忘れずにチェックしてください。

Auth Typeは`None`にします。

![Screenshot 2024-11-02 at 21.48.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/196120a5-222e-071a-7d9f-1e7f4bb7029d.png)

AWS Lambdaのロールは`Create a new role with basic Lambda permissions`（新規作成）を選択します。

![Screenshot 2024-11-02 at 21.47.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/d137edc5-2f75-db48-3c6e-eeaa3f207b73.png)

最後に`Create function`をクリックします。

![Screenshot 2024-11-02 at 21.48.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/2683002c-d7c2-5e54-09cb-6b4bcf742a7f.png)

### 動作確認

作成を実行すると画面がLambdaの編集画面に遷移します。
画面右側にあるURLをクリップボードにコピーして開きます。※赤枠のアイコンをクリックしてください。

![Screenshot 2024-11-02 at 22.06.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/19c11c9c-385f-1ff4-cc02-0f8145eba160.png)

小さく表示されますが、無事にURLを発行できました。

![Screenshot 2024-11-02 at 22.11.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/aeb80da2-9806-c378-5dcb-92bdb25fe14a.png)

## Function URLsはどのようなところに使えるか

動作イメージができたところでそもそもどういうところで使えるのか見ていきたいと思います。
筆者の思いつく範囲では以下のとおりです。

- LINE Messaging APIのWebhookに利用できる
- シンプルにAPIとして利用できる

## LINE Messaging APIのWebhookに利用できる

Messaging APIではWebhook URLを設定しますが、このURLでFunction URLsのURLが利用できます。なお、オウム返しのLINE botを作る場合は以下のPythonコードで実装できます。
※イベントオブジェクトは中身をチェックして返す必要がありますが、そのあたりは割愛

```python
import json
import os
import urllib.request
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)

#環境変数
LINE_CHANNEL_ACCESS_TOKEN   = os.environ['LINE_CHANNEL_ACCESS_TOKEN']

REQUEST_URL = 'https://api.line.me/v2/bot/message/reply'
REQUEST_METHOD = 'POST'
REQUEST_HEADERS = {
    'Authorization': 'Bearer ' + LINE_CHANNEL_ACCESS_TOKEN,
    'Content-Type': 'application/json'
}

def lambda_handler(event, context):

    if not json.loads(event['body'])['events']:
        return 0

    logger.info(json.loads(event['body'])['events'][0]['message'])
    message = str(json.loads(event['body'])['events'][0]['message']['text'])
    reply_token = json.loads(event['body'])['events'][0]['replyToken']

    #返信メッセージ
    REQUEST_MESSAGE = [
        {
            'type': 'text',
            'text': message
        }
    ]
    params = {
        'replyToken': reply_token,
        'messages': REQUEST_MESSAGE
    }
    request = urllib.request.Request(
        REQUEST_URL, 
        json.dumps(params).encode('utf-8'), 
        method=REQUEST_METHOD, 
        headers=REQUEST_HEADERS
        )
    response = urllib.request.urlopen(request, timeout=10)
    return 0
```

## シンプルにAPIとして利用できる

今回は`Auth Type`をNoneに設定して簡単に作成していますが、しっかり設定するとIAMベースの認証APIが作成できます。たとえば、EC2やECSからセキュアなAPIアクセスも可能です。

## 余談：Google CloudのCloud Run functionsでは自動でエンドポイントURLが作成される

サーバレスサービスにURLでアクセスするというと、Google CloudではCloud Run functions（旧：Cloud Functions）というものがあります。

Cloud Run functionsではエンドポイントURLが自動で作成されますが、AWS Lambda Function URLsでは設定していない限りエンドポイントURLが作成されません。

## まとめ

今回はAWS Lambda Function URLsを検証しました。今までAPIを作って対応していたところの一部で便利に利用できると思います。
お試しでLINE botを作るときはAPI Gatewayを作っていましたが、その必要も無くなったのでそういう点でもGoodな機能でした。

## おわり