Consider `mount("/foo", resource)` API
Currently, all resources are implicitly mounted at the root. It would be worthwhile to allow mounting resources at sub paths.
The two options are to either:
a) Add ServiceBuilder::mount("/foo", resource)
b) Replace ServiceBuilder::resource(resource) with a mount API.
Is there the possibility of an API like
ServiceBuilder::new()
.resource(MountBuilder.new().mount("/foo", resource))
That is, Using Resource as the primary abstraction and having mounting reside atop that?
Well, that could work... it is much more verbose though. Conceptually though that strategy would work, assuming we can figure out a shorthand.
it is much more verbose though
For builder-heavy APIs, there are two primary tricks I use to reduce verbosity:
-
Add aliases for constructors —
mount()instead ofMountBuilder.new(), for example.service() .resource({ mount() .at("/foo", resource) .at("/foo", resource)) }) .go()You could also go a step further by creating an alias for the whole shebang, if chaining isn't useful for the inner case:
service() .resource(mount("/foo", resource)) -
Have methods take builders instead of making the user call
build. I snuck that into the code example already, but basically it's just<R: Into<Resource>>and implementFromon the builder. (oh, I wish there wasTryFrom...)
A Rust-specific addition to these ideas is to have extension traits for ServiceBuilder:
trait MountExt {
fn mount(&self, route: &str, resource: Res);
}
impl MountExt for ServiceBuilder { ... }
This latter allows the extremely succinct syntax while still offering the builders for more complicated possibilities. It's a bit annoying because the docs get a bit scattered about. For the purposes of tower-web, you can of course skip these and implement them as inherent methods, but it would allow clean 3rd party integration.
Yeah, I think we can go one of those routes.
Another option I thought of.. add the mount fn on IntoResource?
ServiceBuilder::new()
.resource(users_resource.mount("/users"))
.build()
The disadvantage there is it reads backwards (IMO). I would rather see mount before users_resource.