I am trying to use Serverless Framework to deploy a Python Fast API WebApp. Is is related to issue:
https://github.com/jordaneremieff/mangum/issues/126
When I deploy it using serverless, sls depoy and Invoke the function I am getting the following error:
[ERROR] KeyError: 'requestContext'
Traceback (most recent call last):
File "/var/task/mangum/adapter.py", line 110, in __call__
return self.handler(event, context)
File "/var/task/mangum/adapter.py", line 130, in handler
if "eventType" in event["requestContext"]:
I have tried with python 3.8 and 3.7. Not able to find a resolution on the web for the same. Also tried using the parameters spec_version=2(which is not required I feel).
I feel something is missing here, the issue is somewhere around:
Adapter requires the information in the event and request context to form the ASGI connection scope.
Wondering if anyone has got FastAPI working on AWS Lambda using serverless Framework.
My handler:
from fastapi import FastAPI
from mangum import Mangum
app = FastAPI()
handler = Mangum(app)
@app.get("/ping")
def ping():
return {'response': 'pong'}
serverless.yml:
provider:
name: aws
runtime: python3.8
stage: dev
region: ap-southeast-1
memorySize: 256
functions:
ping:
handler: ping.handler
events:
- http:
path: ping
method: get
cors: true
My requirements.txt
appnope==0.1.0
backcall==0.2.0
certifi==2020.6.20
chardet==3.0.4
click==7.1.2
decorator==4.4.2
fastapi==0.61.1
h11==0.9.0
httpcore==0.10.2
httptools==0.1.1
httpx==0.14.1
idna==2.10
ipython==7.17.0
ipython-genutils==0.2.0
jedi==0.17.2
mangum==0.9.2
parso==0.7.1
pexpect==4.8.0
pickleshare==0.7.5
prompt-toolkit==3.0.6
ptyprocess==0.6.0
pydantic==1.6.1
Pygments==2.6.1
requests==2.24.0
rfc3986==1.4.0
six==1.15.0
sniffio==1.1.0
starlette==0.13.6
traitlets==4.3.3
typing-extensions==3.7.4.2
urllib3==1.25.10
uvicorn==0.11.8
uvloop==0.14.0
wcwidth==0.2.5
websockets==8.1
The issue lies within the mangum adapter expecting input similar to the event content specified by AWS API Gateway shown here. You'll see that there's a requestResponse dictionary there that the Mangum adapter seems to strictly require to function. If your AWS Lambda event doesn't contain that key, then you'll need to add a placeholder field or construct a new context dictionary for it to look for.
This can be done by creating a custom handler as shown within this part of the Mangum docs. If you don't particularly care about what the adapter reads as the context then you can get a working version going with the following:
def handler(event, context):
event['requestContext'] = {} # Adds a dummy field; mangum will process this fine
asgi_handler = Mangum(app)
response = asgi_handler(event, context)
return response
You need to provide at least the minimal Event data, like in the example below,
when you invoke a FastAPI-based lambda function (for example via AWS console Lambda -> Test Event):
{
"resource": "/",
"path": "/api/v1/test/",
"httpMethod": "GET",
"requestContext": {
},
"multiValueQueryStringParameters": null
}
Please see details about the Event format in https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html#apigateway-example-event
The need comes from the mangum adapter for FastAPI, explained in the answer.