4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

LambdaでURLのルーティングを行う

Posted at

はじめに

LambdaでHTTP接続する際、URLのパスで処理を変えたいと思い試した内容を記事にします。

参考

概要

前提として、Pythonを用いています。
以下の2つのやり方を見つけました。

  • AWSGIを使う方法
    • LambdaでFlaskを使える
    • API Gateway経由のeventを処理可能
      • Function URLのeventはできない
  • AWS Lambda Powertoolsを使う方法
    • ユーティリティーのライブラリ
      • 今回のイベントハンドラ以外のユーティリティも提供
      • Python以外の言語でも提供
    • API Gateway経由のeventも、Function URLのeventも可能
      • 未検証だが、ALB経由のも可能な模様

やってみた

いずれの方法もAWS SAMを用いています。私はCloud9上で行いました。

AWSGIを使う方法

使い方は以下のページにありますので、そちらをご参考ください。

Flaskを使われていた方には、いいかもしれません。

AWS Lambda Powertoolsを使う方法

以下のページを参考に、コードを書いてみました。

まず使用するフォルダ、ファイルを作ります。

mkdir -p sample-lambda_powertools/functions && cd sample-lambda_powertools
touch functions/app.py
touch functions/requirements.txt
touch template.yaml

それぞれのファイルに記載していきます。

まずはインポートするモジュールを宣言します。

functions/requirements.txt
aws-lambda-powertools

Function URLの場合

Function URLの場合は、LambdaFunctionUrlResolverを用います。

functions/app.py
from aws_lambda_powertools.event_handler import LambdaFunctionUrlResolver

app = LambdaFunctionUrlResolver()

@app.get("/")
def get_home():
  return "get_home"
  
@app.post("/")
def post_home():
  return "post_home"
  
@app.put("/")
def put_home():
  return "put_home"

@app.delete("/")
def delete_home():
  return "delete_home"

@app.get("/hello")
@app.post("/hello")
def hello():
  return "hello"
  
@app.get("/hello/<inputname>")
@app.post("/hello/<inputname>")
def hello_withname(inputname : str):
  return f"hello {inputname}!"

def lambda_handler(event, context):

  print('sample function')
  return app.resolve(event, context)

Function URLを持つLambdaを作るSAMのテンプレートは以下になります。

template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM Template for Lambda Function

Resources:
  TargetFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: functions/
      Handler: app.lambda_handler
      Runtime: python3.9
      
  TargetFunctionUrl:
    Type: AWS::Lambda::Url
    Properties:
      AuthType: NONE
      TargetFunctionArn: !GetAtt TargetFunction.Arn
      
  TargetFunctionUrlPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunctionUrl
      FunctionName: !GetAtt TargetFunction.Arn
      FunctionUrlAuthType: NONE
      Principal: "*"
      
  FunctionLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/lambda/${TargetFunction}
      RetentionInDays: 3653
      
Outputs:
  FunctionUrl:
    Value: !GetAtt TargetFunctionUrl.FunctionUrl
    Export:
      Name: TargetFunctionUrl

あとはBuildしてDeployです。

sam build && sam validate
sam deploy --guided

CURLコマンドで確かめられられます。

curl -X POST [関数URL]
curl -X POST [関数URL]/hello
curl -X POST [関数URL]/hello/taro

API Gatewayの場合

API Gatewayを使う場合は、APIGatewayRestResolverを用います。
他の部分はFunction URLのコードと変わらないです。

functions/app.py
from aws_lambda_powertools.event_handler import APIGatewayRestResolver

app = APIGatewayRestResolver()

@app.get("/")
def get_home():
  return "get_home"
  
@app.post("/")
def post_home():
  return "post_home"
  
@app.put("/")
def put_home():
  return "put_home"

@app.delete("/")
def delete_home():
  return "delete_home"

@app.get("/hello")
@app.post("/hello")
def hello():
  return "hello"
  
@app.get("/hello/<inputname>")
@app.post("/hello/<inputname>")
def hello_withname(inputname : str):
  return f"hello {inputname}!"

def lambda_handler(event, context):

  print('sample function')
  return app.resolve(event, context)

SAMテンプレートは以下になります。

template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM Template for Lambda Function

Resources:
  TargetFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: functions/
      Handler: app.lambda_handler
      Runtime: python3.9
      Events:
        ApiRoot:
          Type: Api
          Properties:
            Path: '/'
            Method: ANY
        ApiProxy:
          Type: Api
          Properties:
            Path: '/{proxy+}'
            Method: ANY
      
  FunctionLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/lambda/${TargetFunction}
      RetentionInDays: 3653

Outputs:
  TargetdApi:
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"

あとはBuildとDeployで作成し、CURLコマンドで確かめられます。

おわりに

Flaskを勉強していた流れで知った知識であり、色々使いどころがありそうです。
ただ、1つの関数をリッチにしがちになりそうなので、そこは注意が必要かと感じます。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?