I think documentation is pretty clear about it.
"Mounting" means adding a completely "independent" application.
Whatsoever, let's keep going from your example.
This is what we got for our subapi's routes.
[{"path":route.path} for route in subapi.routes] = [
{'path': '/openapi.json'},
{'path': '/docs'},
{'path': '/docs/oauth2-redirect'},
{'path': '/redoc'},
{'path': '/sub'}
]
This is what we got for app's routes.
[{"path":route.path} for route in app.routes] = [{'path': '/openapi.json'},
{'path': '/docs'},
{'path': '/docs/oauth2-redirect'},
{'path': '/redoc'},
{'path': '/app'},
{'path': '/subapi'}
]
That's quite interesting because our subapi did not inherited /app
, let's keep going and make things more interesting, let us run our app with a single command
uvicorn my_app_name:app
As expected we have our app's documentation in /docs
Also we have subapi's documentation in /subapi/docs
, there is not interesting here.
So what we should expect, when we add this?
subapi.mount("/app", app)
Let's run it again, but this time let's call subapi.
uvicorn my_app_name:subapi
What do we expect to see?
- By default we should have subapi's documentation in
/docs
- The app's documentation in the
/app/docs
Yes, we are right, but things goes interesting from here.
Now we have an application like Matryoshka dolls
When we send a request to /app/subapi/sub
(Remind we ran our app with uvicorn my_app_name:subapi
)
curl http://127.0.0.1:8000/app/subapi/sub
Out: {"message":"Hello World from sub API"}
Seems like it's working fine but let's try more.
What about /app/subapi/app/subapi/app/subapi/app/subapi/app/subapi/app/app
curl http://127.0.0.1:8000/app/subapi/app/subapi/app/subapi/app/subapi/app/subapi/app/app
Out: {"message":"Hello World from main app"}
Are you confused? Don't be, let me explain.
When you mount a sub-application, FastAPI takes care of the mounted app, using a mechanism from the ASGI specification called a root_path
What root_path
does and why the example above worked?
Straight-forward root_path
says, you can reach all the routes that you defined in your app.routes
from your root_path
, let's visualize this.
Now our root_path
is /app
/app/
Let's add subapi, and it became our root_path
.
/app/subapi/
Let's add app again, and it became our root_path
/app/subapi/app
- Note: The example above worked because, we mounted two apps together.
Are you not satisfied and you are saying what if I add a middleware, what is going to happen?
Easy to answer, it will not inherit.
Let me explain this with a simple example, I am going to add a middleware for my subapi.
from fastapi.middleware.cors import CORSMiddleware
subapi.add_middleware(CORSMiddleware)
All the data for your application is inside of __dict__
So we can find out the difference easily by checking the 'user_middleware' key.
subapi.__dict__['user_middleware'] = [Middleware(CORSMiddleware)]
app.__dict__['user_middleware'] = []
All the other things you add etc will work independently because they are totally different applications underneath, so you will use mounting safely.
Conclusion
- Yes, they will work independently.