As the codebase grew, Batman wanted to have a way to organise the code. Robyn told him that he had the super power to organise the code in a better way. He told him about the concept of views and subrouters.
Views
To organise your code in a better way - either to group by responsibility or for code splitting, you can use views.
A view, simply is a function with a collection of other closures. e.g.
Request
def sample_view():
def get():
return "Hello, world!"
def post(request):
body = request.body
return Response({"status_code": 200, "description": body, "headers": {}})
The above view contains two closures for the get and the post request.
You can serve views in two ways:
Using an @app.view
decorator.
Request
@app.view("/sync/view/decorator")
def sync_decorator_view():
def get():
return "Hello, world!"
def post(request):
body = request.body
return body
Using the app.add_view
method.
Request
from .views import sample_view
...
...
app.add_view("/", sample_view)
Subrouters
Batman can create subrouters in Robyn. This is useful when you want to group routes together.
Subrouters can be used for both normal routes and web sockets. They are basically a mini version of the main router and can be used in the same way.
The only thing to remember is that you need to add the subrouter to the main router.
Request
from robyn import Robyn, SubRouter
app = Robyn(__file__)
sub_router = SubRouter("/sub_router")
@sub_router.get("/hello")
def hello():
return "Hello, world"
web_socket = SubRouter("/web_socket")
@web_socket.message()
async def hello():
return "Hello, world"
app.include_router(sub_router)
Authentication on Subrouters
Batman asked Robyn how to secure his routes. Robyn explained that authentication can be added to subrouters in three ways, giving developers flexibility to decide the scope and precedence of the authentication.
Important: If any of these methods are used, the authentication for the endpoint is set to
False
unless explicitly overridden.
1. Authentication at the Endpoint Level
Authentication can be applied directly to a specific endpoint using the decorator for that endpoint. This method has the highest precedence, meaning it overrides any authentication settings defined at the router or subrouter level.
Request
from robyn import Robyn, SubRouter
app = Robyn(__file__)
sub_router = SubRouter("/auth_example")
@sub_router.get("/secured", auth_required=True)
def secured(request):
return "This endpoint is secured with authentication!"
@sub_router.get("/unsecured", auth_required=False)
def unsecured(request):
return "This endpoint does not require authentication!"
app.include_router(sub_router)
2. Authentication via include_router
When including a subrouter into the main router, you can specify an authentication flag. This setting applies to all endpoints in the subrouter unless overridden at the endpoint level.
Request
from robyn import Robyn, SubRouter
app = Robyn(__file__)
sub_router = SubRouter("/auth_example")
@sub_router.get("/default_secured")
def default_secured(request):
return "Authentication is set by include_router!"
app.include_router(sub_router, auth_required=True)
3. Authentication at SubRouter Instantiation
Finally, you can define authentication at the time of the SubRouter
instantiation. This acts as the default authentication setting for all endpoints in the subrouter unless overridden by the endpoint decorator or during inclusion into the main router.
Request
from robyn import Robyn, SubRouter
app = Robyn(__file__)
sub_router = SubRouter("/auth_example", auth_required=True)
@sub_router.get("/inherited_auth")
def inherited_auth(request):
return "Authentication is inherited from the SubRouter!"
app.include_router(sub_router)
Precedence Rules
Authentication precedence in Robyn follows this order:
- Endpoint-level decorator: If an endpoint explicitly sets
auth_required=True
orauth_required=False
, this takes priority. include_router
method: The auth_required parameter in app.include_router applies to all endpoints in the included subrouter unless overridden.SubRouter
instantiation: The auth_required setting during SubRouter creation acts as the default for all its endpoints unless overridden at the endpoint or include_router level.
What's next?
Now, that Batman knows how to organise his code, he wants to know how to add dependencies to his code. Robyn tells him that he can add dependencies at the global level, router level and the view level.