Router¶
The Router is the main object that links the whole Ravyn to the Gateway, WebSocketGateway and handlers.
Router class¶
The router class is composed by many attributes that are, by default, populated within the application. However, Ravyn also allows to add extra custom routers, or alternatively, you can add a ChildRavyn app.
from pydantic import BaseModel
from ravyn import Ravyn, Gateway, post
class User(BaseModel):
name: str
email: str
@post("/create")
def create(data: User) -> User: ...
app = Ravyn(routes=[Gateway(handler=create)])
The main Router
class is instantiated within the Ravyn
application with the given routes and the application
starts.
Info
When adding another router to the application, custom routers and
ChildRavyn are available as a way of doing it. One is more limited than
the other, in this case, custom routers are more limited than ChildRavyn
.
Parameters¶
All the parameters and defaults are available in the Router Reference.
Warning
The response_class
, response_cookies
, response_headers
, tags
and include_in_schema
are not used
when add_route is used, only when using ChildRavyn app.
Custom Router¶
Let's assume there are specific customer submodules inside a customers
dedicated file.
There are three ways of separating the routes within the application, using Include,
a ChildRavyn or by creating another router. Let's focus on the latter.
from pydantic import BaseModel
from ravyn import Gateway, JSONResponse, Router, get, post
class Address(BaseModel):
address_line: str
street: str
post_code: str
class Customer(BaseModel):
name: str
email: str
address: Address
@post("/")
def create(data: Customer) -> JSONResponse:
return JSONResponse({"created": True})
@get("/{customer_id:int}")
async def get_customer(customer_id: int) -> JSONResponse:
return JSONResponse({"created": True})
router = Router(
path="/customers",
routes=[
Gateway("/", handler=get_customer),
Gateway("/create", handler=create),
],
)
Above, you created the /application/apps/routers/customers.py
with all the information you need. It does not need
to be in one file, you can have a entirely separate package just to manage the customer, it is up to you.
Now you need to add the new custom router into the main application.
from apps.routers.customers import router as customers_router
from ravyn import Ravyn
app = Ravyn()
app.add_router(customers_router)
This simple and your router is added to the main Ravyn application.
Child Ravyn Application¶
What is this? We call it ChildRavyn
but in fact is simply Ravyn but under a different name mostly for
visualisation purposes and for the sake of organisation.
Check
Using ChildRavyn
or Ravyn
is exactly the same thing, it is only if you prefer to create a
sub application
and you prefer to use a different class instead of Ravyn
to make it more organised.
When organising routes, using the Router
class itself can be a bit limiting because there are certain attributes
that when used within an instance or a Router
to be passed to add_route they will not be picked up.
Example:
response_class
response_cookies
response_headers
tags
include_in_schema
This is not a limitation or a bug, in fact it is intentional as we want to preserve the integrity of the application.
How does it work¶
Let's use the same example used in the custom routers with the customers specific routes and rules.
from pydantic import BaseModel
from ravyn import ChildRavyn, Gateway, JSONResponse, get, post
class Address(BaseModel):
address_line: str
street: str
post_code: str
class Customer(BaseModel):
name: str
email: str
address: Address
@post("/")
def create(data: Customer) -> JSONResponse:
return JSONResponse({"created": True})
@get("/{customer_id:int}")
async def get_customer(customer_id: int) -> JSONResponse:
return JSONResponse({"created": True})
router = ChildRavyn(
routes=[
Gateway("/", handler=get_customer),
Gateway("/create", handler=create),
],
include_in_schema=...,
response_class=...,
response_headers=...,
response_cookies=...,
)
Since the ChildRavyn
is a representation of an Ravyn class, we can pass
the otherwise limited parameters in the custom router and all the parameters available to
Ravyn.
You can add as many ChildRavyn
as you desire, there are no limits.
Now in the main application:
from apps.routers.customers import router as customers_router
from ravyn import Ravyn, Include
app = Ravyn(routes=[Include("/customers", app=customers_router)])
Adding nested applications
from apps.routers.clients import router as clients_router
from apps.routers.customers import router as customers_router
from apps.routers.restrict import router as restrict_router
from ravyn import Ravyn, Include
app = Ravyn(
routes=[
Include("/customers", app=customers_router),
Include(
"/api/v1",
routes=[
Include("/clients", clients_router),
Include("/restrict", routes=[Include("/access", restrict_router)]),
],
),
]
)
The example above shows that you could even add the same application within nested includes, and for each
include, you can add specific unique permissions, middlewares,
exception handlers and dependencies, which are available on each
instance of the Include
. The options are endless.
Note
In terms of organisation, ChildRavyn
has a clean approach to the isolation of responsabilities and allows
treating every individual module separately and simply adding it in to the main application
in the form of Include.
Tip
Treat the ChildRavyn
as an independent Ravyn
instance.
Check
When adding a ChildRavyn
or Ravyn
application, don't forget to add the unique path to the base
Include
, this way you can assure the routes are found properly.
Utils¶
The Router
object has some available functionalities that can be useful.
add_route()¶
from ravyn import Ravyn
app = Ravyn()
app.add_route(
handler=...,
dependencies=...,
exception_handlers=...,
permissions=...,
middleware=...,
name=...,
interceptors=...,
include_in_schema=...,
)
Parameters¶
- name - Name of the route.
- include_in_schema - If route should be added to the OpenAPI Schema
- handler - A HTTP handler.
- permissions - A list of permissions to serve the application incoming requests (HTTP and Websockets).
- middleware - A list of middleware to run for every request. The middlewares of a Include will be checked from top-down.
- interceptors - A list of interceptors or Lilya Middleware, as they are both converted internally. Read more about Python Protocols.
- dependencies - A dictionary of string and Inject instances enable application level dependency injection.
- exception_handlers - A dictionary of exception types (or custom exceptions) and the handler
functions on an application top level. Exception handler callables should be of the form of
handler(request, exc) -> response
and may be be either standard functions, or async functions.
add_websocket_route()¶
from ravyn import Ravyn
app = Ravyn()
app.add_websocket_route(
handler=...,
dependencies=...,
exception_handlers=...,
permissions=...,
middleware=...,
interceptors=...,
name=...,
)
Parameters¶
- name - Name of the route.
- Websocket handler - A websocket handler.
- permissions - A list of permissions to serve the application incoming requests (HTTP and Websockets).
- interceptors - A list of interceptors.
- middleware - A list of middleware to run for every request. The middlewares of a Include will be checked from top-down. or Lilya Middleware as they are both converted internally. Read more about Python Protocols.
- dependencies - A dictionary of string and Inject instances enable application level dependency injection.
- exception_handlers - A dictionary of exception types (or custom exceptions) and the handler
functions on an application top level. Exception handler callables should be of the form of
handler(request, exc) -> response
and may be be either standard functions, or async functions.
add_child_ravyn()¶
from ravyn import ChildRavyn, Ravyn, Gateway, get
@get()
async def home() -> str:
return "home"
child = ChildRavyn(routes=[Gateway(handler=home, name="my-controller")])
app = Ravyn()
app.add_child_ravyn(
path="/child",
child=child,
name=...,
middleware=...,
dependencies=...,
exception_handlers=...,
interceptors=...,
permissions=...,
include_in_schema=...,
deprecated=...,
security=...,
)
Parameters¶
- path - The path for the child ravyn.
- child - The ChildRavyn instance.
- name - Name of the route.
- Websocket handler - A websocket handler.
- permissions - A list of permissions to serve the application incoming requests (HTTP and Websockets).
- interceptors - A list of interceptors.
- middleware - A list of middleware to run for every request. The middlewares of a Include will be checked from top-down. or Lilya Middleware as they are both converted internally. Read more about Python Protocols.
- dependencies - A dictionary of string and Inject instances enable application level dependency injection.
- exception_handlers - A dictionary of exception types (or custom exceptions) and the handler
functions on an application top level. Exception handler callables should be of the form of
handler(request, exc) -> response
and may be be either standard functions, or async functions. - include_in_schema - Boolean if this ChildRavyn should be included in the OpenAPI Schema.
- deprecated - Boolean if this ChildRavyn should be marked as deprecated.