-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Access /docs endpoint in FastAPI function apps #1083
Comments
Any news on this issue? |
I've written a test app to recreate this. The main issue is that the docs site doesn't forward the code key to the openapi.json request. There are a few solutions I can think of (the first is the most practical)
https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/
This would only be the path if (1) is not possible. |
thank you for your help. @tonybaloney the auth option in fastapi is not something id want to do because i like the fact that azure is taking care of the authentication. its part of the service id like to use. the second suggested option is not something i was able to figure out. @maurycyblaszczak-tj this looked most promising and i tried to implement it but failed. are you sure this works with functions? theres a good chance i was just too stupid to succeed. |
Have not tested it but something like this:
In order to work, this requires |
@maurycyblaszczak-tj Thanks again but setting the I also found this thread but I fail to apply the changes to my Azure Function use case. |
I found a workaround that at least brings me to the docs page. however, trying out the API doesn't work this way for obvious reasons. from fastapi.openapi.docs import get_swagger_ui_html
app = FastAPI(docs_url=None)
@app.get("/docs", include_in_schema=False)
async def get_docs(code: str):
openapi_url = "/openapi.json?code=" + code
return get_swagger_ui_html(openapi_url=openapi_url, title="docs") |
Thanks @pietz. Was able to make "try it out "work by including the code as a query argument in all the other endpoints as well. Didn't put effort into reducing the repeated and unused code query argument, but it works. And the documentation tells the user to provide it. Example: @app.get("/")
def root(code: str = Query(..., description="Azure Function App key")):
return {"message": "Hello World"} |
Hm, if the "try it out" isn't working, could the optional Discussion of it in the FastAPI docs: |
FYI, I've created a sample that puts an Azure API Management Policy in front of an authenticated Azure Function, passing along the function-key as part of the policy. I've also set it up such that the API calls require a subscription-key but the docs do not (by creating two "APIs" in APIM with two different policies). Sample here: I know this issue is about doing it entirely within FastAPI, but I think that does require more digging into FastAPI internals as you all have suggested, so I like this approach, plus APIM has some really neat policies you can add on top of the function (rate-limiting, e.g.) |
Update: I also wrote a blog post describing my approach from that sample: |
I recently faced a similar problem. I use V2 model. My app: import logging
import httpx
from httpx import AsyncClient
from fastapi import FastAPI, Request, UploadFile, status
from fastapi.responses import JSONResponse, StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
from starlette.background import BackgroundTask
from config import get_config
config = get_config()
log = logging.getLogger(__name__)
HTTP_SERVER = AsyncClient(base_url=config.api_url)
api = FastAPI(
servers=[{"url": "/api", "description": "API"}],
root_path="/public",
root_path_in_servers=False,
)
api.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"]
)
async def _reverse_proxy(request: Request):
url = httpx.URL(path=request.url.path, query=request.url.query.encode("utf-8"))
rp_req = HTTP_SERVER.build_request(
request.method, url, headers=request.headers.raw, content=await request.body(),
timeout=None
)
rp_resp = await HTTP_SERVER.send(rp_req, stream=True)
return StreamingResponse(
rp_resp.aiter_raw(),
status_code=rp_resp.status_code,
headers=rp_resp.headers,
background=BackgroundTask(rp_resp.aclose),
)
api.add_route("/db", _reverse_proxy, ["GET"])
@api.get("/db")
def get_info():
... host.json {
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[3.3.0, 3.9.0)"
},
"extensions": {
"http": {
"routePrefix": ""
}
}
} but every time I try to call I get "Not Found" for any route. |
Is it the JSON "Not Found" response? That sounds like FastAPI's default response for an undefined route. Typically I get that if I hit up the root of my app and I haven't defined a "/" route. Are you also trying /db, /openapi.json, /docs, etc? |
@pamelafox I am getting a 404 code when I try to call any route. |
I added this suggestion from @pietz and then I use something like modheader to do the api calls at the docs page, this way I don't need to add the code parameter to every call as in @Thyholt suggestion. |
When deploying FastAPI using the ASGI worker,
The
/docs
endpoint only seems to work for "anonymous" functions. Is there anything I can do to use it with authlevel "function"?Question asked by @pietz
The text was updated successfully, but these errors were encountered: