Replies: 19 comments 2 replies
-
Can you share your proxy settings? |
Beta Was this translation helpful? Give feedback.
-
I do not have a proxy. It is a local server. You can run it and test it locally. Please run a file to reproduce: |
Beta Was this translation helpful? Give feedback.
-
@mindej |
Beta Was this translation helpful? Give feedback.
-
@mindej Are you trying to prefix all your end points with |
Beta Was this translation helpful? Give feedback.
-
this might help you. if you require the path should be api/v1/docs, then you can update in the docs_url parameter of fastapi.
|
Beta Was this translation helpful? Give feedback.
-
Like krishnardt says You can change the docs ulr. Documentation |
Beta Was this translation helpful? Give feedback.
-
I also found this double bug. I followed the https://fastapi.tiangolo.com/advanced/behind-a-proxy operation, but did not succeed. I think there should be a bug, please test it. |
Beta Was this translation helpful? Give feedback.
-
This is the expected behaviour, not a bug. |
Beta Was this translation helpful? Give feedback.
-
im seeing similar irritating issues with both lambdas served over an api gatewith with a prefix path and locally, using both root_path and a router with a prefix reading the EXACT DOCS from here https://fastapi.tiangolo.com/advanced/behind-a-proxy/ and setting up the root_path.. also using router it isn't working.. it always just serves things up as if the entire path is always the entire path regardless.. its incredibly infuriating reading doc after doc after doc and following all the the instructures verbatim and not a damn new thing making a damn bit of difference in how its served.. then finding people with the exact same issue being told 'expected behavior not a bug' then what are these worthless features for? how should they work? |
Beta Was this translation helpful? Give feedback.
-
Maybe i totally miss your point, but here are details about my suggestiions. RouterIf you need to place some family of handler with same prefix with direct publishing with your web server, you will need from fastapi import FastAPI
from fastapi.routing import APIRouter
prefix_router = APIRouter()
@prefix_router.get("/path")
def handler():
return "Hello world!"
app = FastAPI()
app.include_router(
prefix_router,
prefix="/prefix"
) ===>
Docs at http://127.0.0.1:8000/docs Root pathIf you need to PUBLISH your app via some proxy with some ADDED prefix, you should use from fastapi import FastAPI
app = FastAPI(root_path="/prefix")
@app.get("/path")
def handler():
return "Hello world!" Going directly to app docs at http://127.0.0.1:8000/docs will show error: Going through proxy like traefik in docs in which you PUBLISHED your server with some prefix will help. [entryPoints]
[entryPoints.http]
address = ":9999"
[providers]
[providers.file]
filename = "routes.toml"
[http]
[http.middlewares]
[http.middlewares.api-stripprefix.stripPrefix]
prefixes = ["/prefix"]
[http.routers]
[http.routers.app-http]
entryPoints = ["http"]
service = "app"
rule = "PathPrefix(`/prefix`)"
middlewares = ["api-stripprefix"]
[http.services]
[http.services.app]
[http.services.app.loadBalancer]
[[http.services.app.loadBalancer.servers]]
url = "http://127.0.0.1:8000" Request through traefik:
Docs through traefik at http://127.0.0.1:9999/prefix/docs |
Beta Was this translation helpful? Give feedback.
-
This thread gave me some hints. I found one missing link that helped me solved the openapi.json ( not_found ) issue. Here is what worked for me I am using nginx as proxy server and For the Here is the sample code for from pydantic import BaseSettings
class Settings(BaseSettings):
app_dir: Path = Path(__file__).parents[1]
base_path: str = "/app"
settings = Settings()
def create_app():
app = FastAPI(
title="MY_APP",
servers=[{"url": settings.base_path}],
root_path=settings.base_path,
)
return app
if __name__ == "__main__":
uvicorn.run("app:create_app", host="0.0.0.0", port=8000, root_path=settings.base_path) Here is a sample code for
|
Beta Was this translation helpful? Give feedback.
-
I am also facing this problem. In my case, I'm using the proxy available in the AWS API Gateway, and it seems that I can only display the Swagger UI (or Redoc) locally or in the deployed API. I can't display both using the same code because of this duplication problem when using root_path. Did anyone figure it out? |
Beta Was this translation helpful? Give feedback.
-
Awesome! It`s realy works great!
Awesome! It`s realy works great! |
Beta Was this translation helpful? Give feedback.
-
FWIW, I was having the same problem on AWS Lambda+API Gateway when the If I used |
Beta Was this translation helpful? Give feedback.
-
I wanted to confirm that I ran into the exactly same issue described by @pjwerneck. My context was exactly the same: API Gateway acting as a proxy and FastAPI configured in Lambda. In my case the additional piece of URL was the default stage name ( I originally included Following the advice above (thanks for it @pjwerneck!), I then prepended I doubt that the sensitivity to the leading slash is intended behavior for the |
Beta Was this translation helpful? Give feedback.
-
I experienced the double-root-path problem on an AWS Lambda + API Gateway with a custom domain with configured base path. Ensuring fastapi's |
Beta Was this translation helpful? Give feedback.
-
Putting FastAPI behind an API Gateway/proxy/load balancer has been a huge chore for me and I'm not sure what the answer is for making this easier to understand but throwing this in for potential future travellers. I think the complication comes from cloud based gateways and us not being in direct control of their entire configuration. YMMV with this but this is what worked for me, I hope it helps someone! My scenario is:
The reason for the load balancer is so we can implement cloud armor (IP allowlisting for our use case primarily) against the cloud run container. The config that worked for me was in the Dockerfile was: inside my api_main.py is: These two sub-apps are defined with the FastAPI class:
Both app_v1 and app_v2 are defined in this way, but have marginally different config like names and the version number. Notably, there is no root_path here either. I have some routers setup and they are included like this:
This includes the router in app_v1 and app_v2, but note that it uses the same router for both, allowing you to serve the same content for both endpoints with one codebase to maintain should only one part of your app have changed between v1 and v2: You can keep the parts that haven't changed consistent. Notably there is no prefix here. Now, when testing locally these addresses all work: But more importantly when I deploy this to cloud run I can use the same paths with a new custom url: This is a very basic working example using the above config
And here's the basic hello world router that lives in routers/helloworld.py if anyone wants it for testing:
You'll get a response from the hello world endpoint like this: |
Beta Was this translation helpful? Give feedback.
-
I have spent some significant time trying to solve this as well. My setup has ALB forwarding requests to an EKS which runs FasAPI (and a Remix based front end). As we've all discovered ALB does not behave as a reverse proxy and forwards the requests in it's entirety (and does not strip the prefix, in my case
I went through various iterations of my solution and finally settled on, a root router that prefixes everything else with a from fastapi import APIRouter
from .auth import router as router_auth
router_root = APIRouter(prefix="/api")
router_root.include_router(
router_auth,
) The FastAPI app has three parameters provided for it all to work behind the ALB:
from fastapi import (
FastAPI,
Request,
status,
WebSocket,
)
from .routers import router_root
app = FastAPI(
title=__title__,
version=__version__,
root_path="/api",
root_path_in_servers=False,
openapi_url="/api/openapi.json", # Adds prefix for AWS loadbalancer
description=settings.api_router.__doc__,
docs_url="/api/docs", # Adding prefix for AWS load balancer
redoc_url=None, # Decided not to serve these docs
terms_of_service=settings.api_router.terms_of_service,
contact=settings.api_router.contact,
openapi_tags=settings.api_router.open_api_tags,
generate_unique_id_function=generate_operation_id,
swagger_ui_parameters={
"url": "/api/openapi.json" # To cater for AWS Loadbalancer not stripping prefix
}
)
app.include_router(router_root) If you are after the entire python project, it's available here on Github. Note: the above changes are not in that repository as we typically don't use AWS. |
Beta Was this translation helpful? Give feedback.
-
I just wanted to add my own use case here as another breadcrumb for the next person as I could see from this page that it must be the same issue, but none of the proposed solutions quite worked exactly as I needed. My use case is I am testing a FastAPI app on AWS Sagemaker including running with Uvicorn (hence, this isn't the production solution but a test case). For reasons I don't claim to understand, the right combination of parameters included a leading slash to
|
Beta Was this translation helpful? Give feedback.
-
Here is error:
Python 3.7.8
fastapi 0.63.0
Run configuration:
uvicorn.run("app:app", host="0.0.0.0", port=port, reload=True)
I think the error is in the path here is console log:
127.0.0.1:54913 - "GET /api/v1/api/v1/openapi.json HTTP/1.1" 404 Not Found
Here is double path: /api/v1/api/v1/
Doc path is wrong http://localhost:8080/docs I expect it to be: http://localhost:8080/api/v1/docs
Here is the test code to reproduce 'test_app.py' file:
Beta Was this translation helpful? Give feedback.
All reactions