litestar
litestar copied to clipboard
Enhancement: Allow re-use of router instances
Summary
Mounting a router to multiple apps raises:
E litestar.exceptions.http_exceptions.ImproperlyConfiguredException: 500: Router with path / has already been registered
There's been some discussion at least in https://github.com/litestar-org/litestar/issues/148 and https://github.com/litestar-org/litestar/issues/1054 and apparently it's not a bug, but intentional. But why does the limitation exist?
The problem is trying to re-use the same router instance when re-creating the application in tests. The first test passes, as the app constructs okay, but when the code is trying to re-build the application for the second test, the error is thrown. This totally kills the ability to create applications with altered configurations in tests.
This is only for the Router instances. If you map controllers directly, then there's no issue.
Could the limitation be lifted?
Basic Example
class MyHandler(Controller): ...
router = Router(route_handlers=[MyHandler])
def create_app():
return Litestar(route_handlers=[router])
@pytest.fixture(scope="function")
def client():
return TestClient(app=create_app())
def test_one(client):
pass
def test_two(client):
pass
Drawbacks and Impact
No response
Unresolved questions
No response
[!NOTE]
While we are open for sponsoring on GitHub Sponsors and OpenCollective, we also utilize Polar.sh to engage in pledge-based sponsorship.Check out all issues funded or available for funding on our Polar.sh dashboard
- If you would like to see an issue prioritized, make a pledge towards it!
- We receive the pledge once the issue is completed & verified
- This, along with engagement in the community, helps us know which features are a priority to our users.
The reason for this is that the components are "bound" to the layers above them. This enables you to define them in an unbound state (i.e. compared to something like @app.get("/")) but still provide access to the upper layers needed to resolve things like middlewares, dependencies and guards from them.
For controllers and handlers this is solved by not registering them directly, but instead creating a copy of them internally. We should do the same for routers I think. @peterschutt?
Sounds reasonable to me, at least it would be consistent.
I hit this some time ago, and started using router factories rather than instantiating a global scoped router, its worked well enough that I'd forgotten this was an issue.
A fix for this issue has been released in v2.7.0