Closed Ogeon closed 8 years ago
I did something like this for a test application with multiple app support: https://github.com/FerarDuanSednan/pilum
Have a look at those files:
I encapsulated the specifics enums to a global one like this:
use rustful::{Handler, Context, Response};
use app::AppHandler;
use app2::App2Handler;
pub enum AppRoutes {
App(AppHandler),
App2(App2Handler)
}
impl Handler for AppRoutes {
fn handle_request(&self, context: Context, response: Response) {
match *self {
AppRoutes::App(ref a) => a.handle_request(context, response),
AppRoutes::App2(ref a) => a.handle_request(context, response)
}
}
}
I don't know if it will help you implementing this :)
PS: I'm not a native English speaker, sorry if some terms are incorrect :)
Sure, that works for selecting a handler post-routing. The idea with this change is to take it a step further and do kind of the same with routers. Here's a sketch of the behavior:
in main_router.find:
"routers/a" => router_a.find(...),
"routers/b" => router_b.find(...)
To explain further (I wasn't able to write anything longer yesterday): The standard router API assumes that there is only one router that takes the whole URL and spits out a handler. This can be a bit too rigid and makes it harder/less intuitive to implement composite routers, where the first part of the URL is processed by a "main router" and the rest is processed by sub routers (or with some other selection method).
All of this may be trickier than I thought. One problem is that a Handler
is a Router
that matches anything, while a proper TreeRouter
requires an exact match to pick a Handler
. It's therefore not possible to just treat handlers as routers. Routers in routers must be treated as branches and not leaves.
P.S. Your English is fine. Don't worry :)
I found an other way to do this without breaking everything : encapsulate the handlers into Boxes.
// app/mod.rs
pub fn get_routes() -> TreeRouter<Box<Handler>> {
let router = insert_routes! {
TreeRouter::new() => {
Get : Box::new(AppHandler::MainController("great")) as Box<Handler>,
":person" => Get : Box::new(AppHandler::MainController("great")) as Box<Handler>
}
};
router
}
// app2/mod.rs
pub fn get_routes() -> TreeRouter<Box<Handler>> {
let router = insert_routes! {
TreeRouter::new() => {
Get : Box::new(App2Handler::WebControllerIndex) as Box<Handler>,
":person" => Get : Box::new(App2Handler::WebControllerIndex) as Box<Handler>
}
};
router
}
// config/routes.rs
pub fn get_routes() -> TreeRouter<Box<Handler>> {
let mut router = TreeRouter::new();
router.insert_router("/", app::get_routes());
router.insert_router("/app2", app2::get_routes());
router
}
I don't know if it's possible to add this to the core ( or to update the insert_routes! macro to make things easier ).
Yeah, that works as long as we are dealing with only TreeRouter
, but what if you want to plug in some MySpecialRouter
as a child router? That's when things becomes less ergonomic. The TreeRouter
is already built as a recursive structure, which works because it has access to the content of its children, but attaching an arbitrary router introduces a black box into the system.
This would enable much more flexibility when it comes to how requests are handled, by allowing composition of multiple router types. The fact that
Handler
impliesRouter
makes the leap a bit shorter, and the main change is probably to not assume that routers stores handlers, but I'm sure there will be rings on the water.