FastAPIでswagger-uiを表示する

2023/01/16に公開

前回

https://zenn.dev/shigeru_oda/articles/f1d360786c41568d16fa

今回やりたいこと

前回作ったSAMを使ったHelloWorldをベースにFastAPI、MangumからAPIドキュメント(swagger-ui)を作る

環境整備

■pip install

install

pip install fastapi
pip install mangum
pip install uvicorn

hello_worldを書き換え

■app.py

~/environment/sam-app-1/hello_world/app.pyを以下内容で書き換え

from fastapi import FastAPI
from mangum import Mangum

app = FastAPI()

@app.get("/hello")
def root():
    return {"message": "Hello World1"}

lambda_handler = Mangum(app)

■requirements.txt

~/environment/sam-app-1/hello_world/requirements.txtを以下内容で書き換え

requests
fastapi
mangum

template.yamlを書き換え

■template.yaml

~/environment/sam-app-1/template.yamlを以下内容で書き換え
変更点はタイムアウトを10sに変更・追加したのみ

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 10
    MemorySize: 128

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.9
      Timeout: 10
      Architectures:
        - x86_64
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

build、invoke、deploy

■sam build

実行

cd ~/environment/sam-app-1/
sam build

結果

sam build
Building codeuri: /home/ec2-user/environment/sam-app-1/hello_world runtime: python3.9 metadata: {} architecture: x86_64 functions: HelloWorldFunction
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {{stack-name}} --watch
[*] Deploy: sam deploy --guided

■sam local invoke

FastAPI、Mangumを咬ましたので直接実行はエラーになります

sam local invoke
Invoking app.lambda_handler (python3.9)
Skip pulling image and use local one: public.ecr.aws/sam/emulation-python3.9:rapid-1.70.0-x86_64.

Mounting /home/ec2-user/environment/sam-app-1/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container
START RequestId: 68a95560-863c-40ee-b1ae-da964146a58a Version: $LATEST
[ERROR] RuntimeError: The adapter was unable to infer a handler to use for the event. This is likely related to how the Lambda function was invoked. (A    raise RuntimeError(  # pragma: no cover68, in inferl__alid for a supported handler.)
END RequestId: 68a95560-863c-40ee-b1ae-da964146a58a
REPORT RequestId: 68a95560-863c-40ee-b1ae-da964146a58a  Init Duration: 0.05 ms  Duration: 745.57 ms     Billed Duration: 746 ms Memory Size: 128 MB   Max Memory Used: 128 MB
{"errorMessage": "The adapter was unable to infer a handler to use for the event. This is likely related to how the Lambda function was invoked. (Are you testing locally? Make sure the request payload is valid for a supported handler.)", "errorType": "RuntimeError", "requestId": "68a95560-863c-40ee-b1ae-da964146a58a", "stackTrace": ["  File \"/var/task/mangum/adapter.py\", line 76, in __call__\n    handler = self.infer(event, context)\n", "  File \"/var/task/mangum/adapter.py\", line 68, in infer\n    raise RuntimeError(  # pragma: no cover\n"]}

■sam local start-api

実行

sam local start-api

別ターミナルでAPI CALL

curl http://127.0.0.1:3000/hello

結果

Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. If you used sam build before running local commands, you will need to re-run sam build for the changes to be picked up. You only need to restart SAM CLI if you update your AWS SAM template
2023-01-16 13:08:05  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
Invoking app.lambda_handler (python3.9)
Skip pulling image and use local one: public.ecr.aws/sam/emulation-python3.9:rapid-1.70.0-x86_64.

Mounting /home/ec2-user/environment/sam-app-1/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container
START RequestId: 795ee2be-9cc3-4a36-91c7-bcd300492028 Version: $LATEST
END RequestId: 795ee2be-9cc3-4a36-91c7-bcd300492028
REPORT RequestId: 795ee2be-9cc3-4a36-91c7-bcd300492028  Init Duration: 0.20 ms  Duration: 569.09 ms     Billed Duration: 570 ms Memory Size: 128 MB   Max Memory Used: 128 MB
2023-01-16 13:08:58 127.0.0.1 - - [16/Jan/2023 13:08:58] "GET /hello HTTP/1.1" 200 -

別ターミナルの結果

{"message":"Hello World"}

■sam deploy

実行

sam deploy

結果

sam deploy
Uploading to sam-app-1/cab4ea6d13ce8e849c25c66b3dda7c2d  4038327 / 4038327  (100.00%)

        Deploying with following values
        ===============================
        Stack name                   : sam-app-1
        Region                       : ap-northeast-1
        Confirm changeset            : False
        Disable rollback             : False
        Deployment s3 bucket         : aws-sam-cli-managed-default-samclisourcebucket-1hsg213hvqm87
        Capabilities                 : ["CAPABILITY_IAM"]
        Parameter overrides          : {}
        Signing Profiles             : {}

Initiating deployment
=====================
Uploading to sam-app-1/b4b8766f3a8a434d20ab4f15f37a8f7c.template  1221 / 1221  (100.00%)

Waiting for changeset to be created..
CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------------------------------
Operation                            LogicalResourceId                    ResourceType                         Replacement                        
-------------------------------------------------------------------------------------------------------------------------------------------------
* Modify                             HelloWorldFunction                   AWS::Lambda::Function                False                              
* Modify                             ServerlessRestApi                    AWS::ApiGateway::RestApi             False                              
-------------------------------------------------------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:123456789012:changeSet/samcli-deploy1673874665/3b354b55-5629-479d-9445-ff2ece1ea14c


2023-01-16 13:11:16 - Waiting for stack create/update to complete

CloudFormation events from stack operations (refresh every 0.5 seconds)
-------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                       ResourceType                         LogicalResourceId                    ResourceStatusReason               
-------------------------------------------------------------------------------------------------------------------------------------------------
UPDATE_IN_PROGRESS                   AWS::Lambda::Function                HelloWorldFunction                   -                                  
UPDATE_COMPLETE                      AWS::Lambda::Function                HelloWorldFunction                   -                                  
UPDATE_COMPLETE_CLEANUP_IN_PROGRES   AWS::CloudFormation::Stack           sam-app-1                            -                                  
S                                                                                                                                                 
UPDATE_COMPLETE                      AWS::CloudFormation::Stack           sam-app-1                            -                                  
-------------------------------------------------------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
----------------------------------------------------------------------------------------------------------------------------------------------------
Outputs                                                                                                                                            
----------------------------------------------------------------------------------------------------------------------------------------------------
Key                 HelloWorldFunctionIamRole                                                                                                      
Description         Implicit IAM Role created for Hello World function                                                                             
Value               arn:aws:iam::123456789012:role/sam-app-1-HelloWorldFunctionRole-1XQBL5UFOATLL                                                  

Key                 HelloWorldApi                                                                                                                  
Description         API Gateway endpoint URL for Prod stage for Hello World function                                                               
Value               https://xxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/                                                        

Key                 HelloWorldFunction                                                                                                             
Description         Hello World Lambda Function ARN                                                                                                
Value               arn:aws:lambda:ap-northeast-1:123456789012:function:sam-app-1-HelloWorldFunction-5dZOxwSuoqyf                                  
----------------------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - sam-app-1 in ap-northeast-1

API Call

curl https://xxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello

API Call結果

{"message":"Hello World"}

uvicornの実行

■uvicornの実行

実行

cd ~/environment/sam-app-1/hello_world/
uvicorn app:app --reload

結果

INFO:     Will watch for changes in these directories: ['/home/ec2-user/environment/sam-app-1/hello_world']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [23249] using StatReload
INFO:     Started server process [23280]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

■uvicornの実行

uvicornがデフォでは8000portを利用しますが、Cloud9の仕様に合わせるため8080portを指定します

実行

uvicorn app:app --reload --port 8080  

swagger-ui

Cloud9 Header -> Preview -> Preview Running Applicationで画面表示後、Pathに/docsを指定します
swagger-uiでAPI Callも可能です。

参考

■fastapi

https://fastapi.tiangolo.com/ja/

■mangum

https://mangum.io/

Discussion