Skip to content

Fix openapi document with dependencies override (#5451)#5452

Closed
lmignon wants to merge 5 commits intofastapi:masterfrom
lmignon:master-fix-openapi-with-overrides
Closed

Fix openapi document with dependencies override (#5451)#5452
lmignon wants to merge 5 commits intofastapi:masterfrom
lmignon:master-fix-openapi-with-overrides

Conversation

@lmignon
Copy link

@lmignon lmignon commented Oct 2, 2022

refs #5451

@github-actions
Copy link
Contributor

github-actions bot commented Oct 2, 2022

📝 Docs preview for commit aed607d at: https://6339f3a6e3f39c274895ddee--fastapi.netlify.app

@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from aed607d to acf37ee Compare October 2, 2022 20:41
@github-actions
Copy link
Contributor

github-actions bot commented Oct 2, 2022

📝 Docs preview for commit acf37ee at: https://6339f80a0dfefb27382a1ac6--fastapi.netlify.app

@lmignon lmignon marked this pull request as draft October 2, 2022 20:49
@codecov
Copy link

codecov bot commented Oct 3, 2022

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (cf73051) to head (e31a2c3).
Report is 1336 commits behind head on master.

❗ Current head e31a2c3 differs from pull request most recent head 9ae3c2e. Consider uploading reports for the commit 9ae3c2e to get more accurate results

Additional details and impacted files
@@            Coverage Diff            @@
##            master     #5452   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          540       542    +2     
  Lines        13969     14003   +34     
=========================================
+ Hits         13969     14003   +34     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@github-actions
Copy link
Contributor

github-actions bot commented Oct 3, 2022

📝 Docs preview for commit e5396cd at: https://633b40fa63c4ac2ee3f06d9d--fastapi.netlify.app

@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from e5396cd to 4ad2bc3 Compare October 3, 2022 20:09
@lmignon lmignon marked this pull request as ready for review October 3, 2022 20:11
@github-actions
Copy link
Contributor

github-actions bot commented Oct 3, 2022

📝 Docs preview for commit 4ad2bc3 at: https://633b422f18b80c30ba4d1c06--fastapi.netlify.app

@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from 4ad2bc3 to ee235fb Compare October 3, 2022 20:17
@github-actions
Copy link
Contributor

github-actions bot commented Oct 3, 2022

📝 Docs preview for commit ee235fb at: https://633b441611b92d32862315ee--fastapi.netlify.app

@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from ee235fb to 39fb6b4 Compare October 3, 2022 20:24
@github-actions
Copy link
Contributor

github-actions bot commented Oct 3, 2022

📝 Docs preview for commit 39fb6b4 at: https://633b45949cb90d34d468a0a3--fastapi.netlify.app

@github-actions
Copy link
Contributor

github-actions bot commented Oct 4, 2022

📝 Docs preview for commit 3f7a29c at: https://633c175b5c3f4076c7a5e89e--fastapi.netlify.app

@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from 3f7a29c to 7ba81c5 Compare October 4, 2022 11:25
@lmignon
Copy link
Author

lmignon commented Oct 4, 2022

This PR also includes a commit to pin the version of trio since the last version 0.22.0 breaks tests. A fix is proposed here #5456

@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from 7ba81c5 to e31a2c3 Compare October 4, 2022 11:29
@github-actions
Copy link
Contributor

github-actions bot commented Oct 4, 2022

📝 Docs preview for commit e31a2c3 at: https://633c19e333bbe9797f5dda49--fastapi.netlify.app

Copy link
Contributor

@yezz123 yezz123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@lmignon
Copy link
Author

lmignon commented Nov 14, 2022

@tiangolo No news about this one? IMO this changes makes a lot of sense but the way I fixed the code is may be not appropriate since that's the first time I dig into it.

@github-actions
Copy link
Contributor

📝 Docs preview for commit db3212f at: https://639cda9b2c118d005f47f6ee--fastapi.netlify.app

@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from db3212f to b915ccf Compare March 10, 2023 10:09
@github-actions
Copy link
Contributor

📝 Docs preview for commit b915ccf at: https://640b02dc77012078081ced3e--fastapi.netlify.app

@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from b915ccf to 3b7895b Compare June 9, 2023 14:52
@lmignon
Copy link
Author

lmignon commented Jun 9, 2023

@tiangolo I rebased this branch on 0.96.0. I hope it will find a path to be included into a next release.

@github-actions
Copy link
Contributor

github-actions bot commented Jun 9, 2023

📝 Docs preview for commit 3b7895b at: https://64833db8a9aabd1989f2d478--fastapi.netlify.app

@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from 3b7895b to cb8573b Compare June 22, 2023 08:38
@lmignon
Copy link
Author

lmignon commented Jun 22, 2023

rebased on 0.97

@lmignon
Copy link
Author

lmignon commented Jun 26, 2023

rebased on 0.98

@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch 2 times, most recently from 38efd0c to 973a53e Compare September 18, 2023 15:24
@lmignon lmignon marked this pull request as draft September 19, 2023 07:33
@lmignon
Copy link
Author

lmignon commented Sep 19, 2023

I'll adapt the code to work on the 1.X version

@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from 9a1fadd to 344e322 Compare October 6, 2023 16:34
@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from 344e322 to 7f11e98 Compare November 20, 2023 18:54
@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from 61fdc10 to eb35b5f Compare February 13, 2024 17:31
@lmignon lmignon marked this pull request as ready for review February 14, 2024 07:32
@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from 6280f4f to 9ae3c2e Compare March 13, 2024 14:40
@lmignon
Copy link
Author

lmignon commented Mar 13, 2024

rebased on 0.110.0

@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from 9ae3c2e to dc1b214 Compare September 20, 2024 14:04
@lmignon lmignon force-pushed the master-fix-openapi-with-overrides branch from 75389c4 to 8413c75 Compare September 20, 2024 14:09
@lmignon
Copy link
Author

lmignon commented Sep 20, 2024

rebased on 0.115.0

@tiangolo Any chance to get this reviewed or better merged? It's very useful. Thank you.

@sebastienbeau
Copy link

@tiangolo We are interested too. Thanks @lmignon for your work

@marielejeune
Copy link

@tiangolo I'm also interested! Could you please have a look? Thanks

Copy link
Member

@YuriiMotov YuriiMotov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could anyone describe a real use case when you need to test openapi schema generated with overridden dependencies?

Regarding the use case described in #5451 (and discussion #8392), I believe this is a misuse of dependencies_override and should be encouraged..

@lmignon
Copy link
Author

lmignon commented Jun 12, 2025

@YuriiMotov

We use FastAPI's dependency override mechanism to create generic endpoint modules that declare what they need, but not how to get it. This allows us to build reusable API fragments, tailor behavior per deployment, and cleanly separate concerns. It's a lightweight and powerful way to introduce inversion of control in REST API design.


💡 Context

FastAPI currently provides app.dependency_overrides as a way to override dependencies — a feature that's primarily documented and discussed in the context of testing.

However, We are using this mechanism in production, not for testing, but to enable modular and context-adaptable API composition. This usage pattern has proven extremely powerful in promoting clean architecture, reusable API fragments, and dependency inversion.

I would like to propose that this usage be recognized and supported in the documentation — and ideally improved to fully support production use, particularly in relation to OpenAPI schema generation.


✅ Use Case: Building Reusable API Fragments

We build endpoint modules that:

  • Declare abstract dependencies using Depends(...)
  • Do not hardcode how context-specific data (like the current user, tenant, or config) is obtained
  • Can be reused across different apps or clients

At application startup, we use app.dependency_overrides[...] = ... to inject concrete implementations according to the current context:

# api/user.py
from fastapi import APIRouter, Depends
from .schemas import User

def get_user() -> User:
    raise NotImplementedError("Override this in your app")

router = APIRouter()

@router.get("/me")
def get_me(user: User = Depends(get_user)):
    return {"username": user.username}

# main.py
from fastapi import FastAPI
from api.user import router as user_router, get_user
from .auth import get_current_user_from_oauth

app = FastAPI()

app.include_router(user_router)

# Runtime context binding
app.dependency_overrides[get_user] = get_current_user_from_oauth

💪 Benefits of This Pattern

  1. Modularity & Reusability
    API logic becomes portable across projects. For example, the same user endpoints can be reused whether the context uses OAuth2, SSO, API keys, or a static user mock.
  2. Separation of Concerns
    Endpoints focus only on what they need, not how it's obtained. Dependency resolution is centralized during app setup.
  3. Contextual Adaptation
    At deployment time, we can easily swap in context-specific dependencies:
    • SaaS vs. on-premise
    • Auth method differences
    • Multi-tenant logic
    • A/B testing

In short:

  • Separation of concerns: endpoint logic is decoupled from its environment
  • Reusability: endpoint modules become portable and plug-and-play
  • Customizability: each app or deployment can inject its own context logic
  • Testability: remains fully compatible with test-time overrides
  • Clean architecture: enables inversion of control with minimal boilerplate

This usage aligns closely with dependency injection best practices found in frameworks like Spring, Angular, or ASP.NET Core — and works extremely well within FastAPI's design philosophy.


⚠️ Limitation: OpenAPI Inaccuracy

The only real issue we've encountered is that the generated OpenAPI schema doesn't reflect overridden dependencies. For example:

  • Security schemes introduced by the override (e.g., OAuth2) are not documented
  • Request/response models from the override are not shown
  • Parameter differences may be silently omitted

We understand that OpenAPI generation happens statically, while dependency_overrides is dynamic. However, this is the main blocker to using this pattern with full confidence in production. Nevertheless, even if the current PR is not correctly written, it at least proves that it is possible to modify the current implementation to make it dynamic.


🙏 Thanks

FastAPI’s dependency injection system is one of its strongest features. We'd love to see this powerful and flexible mechanism promoted more broadly as a foundation for clean, modular API architecture — beyond testing.

Thanks for your amazing work!

Copy link

@sebastienbeau sebastienbeau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested, and used in production !
Thanks for your work @lmignon

@tiangolo
Copy link
Member

Thanks for the interest and for the detailed explanation! 🍰

The current intention of dependency overrides is mainly for tests. Maybe it would make sense to allow a more general way to allow defining dependency overrides in production, but in that case, I think it would probably need a different interface than what is currently available in FastAPI. This might be related to a large refactor I want to do later with how routers work.

Nevertheless, I would get nervous if the overriding dependency is so different that it would generate a different OpenAPI schema, I would think that then it would probably be doing too much, in a very different way, so I would prefer not to have that.

The other part is, any new change or feature I accept, I have to keep maintaining it going forward, and fix any and all the possible side effects and potential breaks it could cause.

I might revisit this idea in the future, but probably in a different way, after some other reactors and features I need to make.

For now, I prefer to pass on this one, but thanks for all the effort put into it! ☕ 🍰

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants