Skip to content
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

Nesting FastAPI instances doesn't work very well #8

Closed
kkinder opened this issue Jan 13, 2019 · 8 comments
Closed

Nesting FastAPI instances doesn't work very well #8

kkinder opened this issue Jan 13, 2019 · 8 comments
Labels
answered feature New feature or request reviewed

Comments

@kkinder
Copy link
Contributor

kkinder commented Jan 13, 2019

Do this:

main_app = FastAPI()
sub_api = FastAPI()

...
main_app.router.routes.append(Mount('/subapi', app=sub_api))

sub_api will correctly serve ever /subapi -- docs, methods, all that. However, the docs will still look for /openapi.json (absolute link) when trying to load the openapi spec. Additionally, the spec will not be adjusted to have the correct links, relative to where the module is mounted.

Perhaps this is a corner use case, but a lot of apps might have different collections of routes mounted in different subpaths.

@tiangolo
Copy link
Owner

There's something similar (but not the same) to handle those cases: APIRouter.

It also allows having the routes in different files. And it allows including routers with path prefixes that apply to all of them.

It wasn't properly documented, but it is now: https://fastapi.tiangolo.com/tutorial/bigger-applications/

E.g. a file at app/routers/users.py with:

from fastapi import APIRouter

router = APIRouter()


@router.get("/users/", tags=["users"])
async def read_users():
    return [{"username": "Foo"}, {"username": "Bar"}]

And a file at app/main.py with:

from fastapi import FastAPI

from .routers.users import router

app = FastAPI()

app.include_router(router)

It doesn't "mount" the route, but clones its routes. And the OpenAPI schema (and docs) end up together.

Does that work for your use case?

@kkinder
Copy link
Contributor Author

kkinder commented Jan 18, 2019

Hey, thanks for the code example and suggestion.

Unfortunately it doesn't ft what I have in mind. The idea is to have two APIs each, with their own separate docs, OpenAPI files, etc, at different bases.

For example, you might have /public/* to serve /public/docs, /public/openapi.json, etc, for public use.

For internal use, you might have have /internal/* with the same set of resources. Essentially two FastAPI instances.

This could also be useful for doing something like versioning.

@haizaar
Copy link
Contributor

haizaar commented Feb 14, 2019

@kkinder Can you share why do you want to server both public and internal stuff from the same instance? Isn't there a security contradiction?

@kkinder
Copy link
Contributor Author

kkinder commented Feb 14, 2019

@haizaar No, that's not a security problem at all. Both APIs have access to the same database, same permissions, etc.

It's more that I don't want to expose methods I intend to change the signature of soon to potential end-users.

@haizaar
Copy link
Contributor

haizaar commented Feb 14, 2019

@kkinder I see - so it's not internal (network-wise) API, but rather external API that serves both internal users and other users. If so, then I wonder why not having separate backends for those and route traffic to them using API GW? Should help with independent updates, etc.

@kkinder
Copy link
Contributor Author

kkinder commented Feb 14, 2019

@haizaar Just more hassle. The model is the same, the authentication is the same, the middleware is the same, the update cycle is the same. I just want some methods listed on different swagger files, more or less.

@tiangolo
Copy link
Owner

Guys, this should be solved by PR #26 by @kabirkhan.

It is released as 0.4.0, the new docs are here: https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/ 🎉 🚀

Let me know if it works for you.


As a side note, I think I tend to do the same as @haizaar, to set up different APIs in different backends (and different containers too), and then put them behind a load balancer (Traefik in my case).

But I also see how @kkinder's use case and others including having a reverse proxy make this feature relevant (so much there's another issue and this PR from above).

@tiangolo
Copy link
Owner

I guess this was solved. I'll close this issue now. But feel free to add more comments or create new issues.

@tiangolo tiangolo added feature New feature or request answered reviewed labels Feb 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
answered feature New feature or request reviewed
3 participants