I have an AWS Lambda function which I can't seem to hook up to a custom domain using AWS API Gateway. I consistently get a {"detail":"Not Found"}
error when I curl:
https://api.domain.com/api/v1/users
https://api.domain.com/api/v1/users/1
I added a catch all to return the method and the request with the code looking like this but I can't see how to match it to the returned url:
from fastapi import FastAPI, Request
from mangum import Mangum
app = FastAPI() # /api/v1/users/
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/users")
def read_root():
return {"Hello": "Users"}
@app.get("/users/{user_id}")
def user_item(user_id: int, q: str = None):
return {"user_id": user_id, "q": q}
# My catch all code
#@app.api_route("/{path_name:path}", methods=["GET"])
#async def catch_all(request: Request, path_name: str):
# return {"request_method": request.method, "path_name": path_name}
handler = Mangum(app, lifespan="off")
Which, when uncommented returns the path_name correctly:
{"request_method":"GET","path_name":"api/v1/users"}
{"request_method":"GET","path_name":"api/v1/users/1"}
I am totally stuck but I think it's something to do with either a prefix or a default root.
So 3 things were required to fix this:
api_gateway_base_path='/api/v1/users'
so Mangum knew where the AWS root path of api.domain.com/api/v1/users
was. This gave me no docs but did allow me to access /users/
and /users/whatever
root_path="/api/v1/users"
which then enabled me to access api.domain.com/api/v1/users/docs
api.domain.com/api/v1/users
was still "not found". In order to solve this I had to add an additional route @app.get('', include_in_schema=False)
to capture routes which had no trailing forward slash. I added the False for include_in_schema so the automatic documentation system wasn't generating the same docs for the same route.Final code looked like this:
from datetime import datetime
from fastapi import FastAPI, Request
from mangum import Mangum
from pydantic import BaseModel
app = FastAPI(
root_path="/api/v1/users"
)
@app.get('', include_in_schema=False)
@app.get("/")
def read_root(request: Request):
return {"Hello": "Users"}
# @app.api_route("/{path_name:path}", methods=["GET"])
# async def catch_all(request: Request, path_name: str):
# print(request.scope)
# return {
# "request_method": request.method,
# "root_path": request.scope['root_path'],
# "raw_path": request.scope['raw_path'],
# "path": request.scope['path'],
# "path_name": path_name
# }
handler = Mangum(
app,
lifespan="off",
api_gateway_base_path='/api/v1/users'
)