Neoteroi / BlackSheep

Fast ASGI web framework for Python
https://www.neoteroi.dev/blacksheep/
MIT License
1.88k stars 78 forks source link

Inherit endpoints from the base controller #511

Open ewarchul opened 3 months ago

ewarchul commented 3 months ago

Hello, first off -- thank you for your work on this great framework! I would like to know if the framework somehow allows the inheritance of registered endpoints from the base class.

Example:

class Base(Controller): 
    path: ClassVar[str] = 'base'
    @classmethod
    def route(cls) -> Optional[str]:
        return f'/api/{cls.path}'

    @get('/foo')
    def foo():
        return ok() 

class Dervied(Base):
    path = 'derived'

Expected behavior:

It should be possible to GET the following endpoints /api/base/foo and /api/derived/foo.

Currently, only the former endpoint is accessible.

sinisaos commented 1 month ago

@ewarchul I tried using two class variables and not using the classmethod route and then passing these two variables to the operation decorator and everything works for both parent and child classes. Something like this

Example code ```python from blacksheep import Application from blacksheep import get, text from blacksheep.server.controllers import Controller from typing import ClassVar app = Application() class Base(Controller): api_path: ClassVar[str] = "api" path: ClassVar[str] = "base" @get("/{api_path}/{path}/foo") async def foo(request): return text(f"Path: {request.path}") @get("/{api_path}/{path}/foo/{name}") async def greet(request): param = request.route_values["name"] return text(f"Hello {param}, Path is {request.path}") class Derived(Base): path = "derived" class Other(Base): path = "other" ```

Result is

> curl -X GET 'http://localhost:8000/api/base/foo'
Path: /api/base/foo
> curl -X GET 'http://localhost:8000/api/derived/foo'
Path: /api/derived/foo
> curl -X GET 'http://localhost:8000/api/other/foo'
Path: /api/other/foo
> curl -X GET 'http://localhost:8000/api/base/foo/John'
Hello John, Path is /api/base/foo/John
> curl -X GET 'http://localhost:8000/api/derived/foo/John'
Hello John, Path is /api/derived/foo/John
> curl -X GET 'http://localhost:8000/api/other/foo/John'
Hello John, Path is /api/other/foo/John

Hope this helps and sorry if I missed your point.