Perhaps this is documented somewhere, but I'm digging through the source and it doesn't seem obvious that this is supported.
I want to match everything at a specific path, /git in this instance. I'd like to construct a function with the various matchers/guards as currently supported, but then to perform all significant handling within that function based on method type, parameter presence, etc.
I believe this feature is necessary because, as documented, route-matching is very specific. This is great for things like typed APIs, but some API boundaries are already well-structured and don't need that much help from Rust.
My use case is proxying everything under /git to a Rust function that calls git http-backend. git-http-backend is specified well enough that I'd trust it as is. Sometimes the URI has query parameters, sometimes it doesn't. I think the methods used vary as well. But right now I don't see how to specify that I want everything under /git passed to this function. This would also be useful for, say, CGI handling or embedded HTTP proxies.
I can define a route like so:
#[get("/git/<path..>?<query>")]
but that won't work for POSTs, nor for requests that don't include query parameters, of which there are several I think (I'm very much implementing this for the first time so am learning as I go.) In the end, maybe I could have bunches of routes specifying every possibility, and proxy their calls to a central function. But that's ugly, and as nice as it'd be to fully type that API boundary in Rust, I trust git-http-backend well enough for this weekend side project. :)
I think this needs to be in Rocket because it changes how the router works. At the moment it looks like everything is tied to a single method, and query parameters can't be optional. Instead of adding a bunch of extra code covering every corner case (support for all methods in specific routes, support for everything-optional) it might make sense to just proxy every matching path to a handler. Call it unsafe for routes if you like. :)
Thanks.
This is possible in master with manual routing. The gist of a solution would be to create a Route instance for every HTTP method to the path /<path..>, each pointing to the same handler. In master, if you don't specify a query parameter in the path matcher, then Rocket will match requests with and without a query parameter (see https://github.com/SergioBenitez/Rocket/issues/185#issuecomment-292052648 and 9160483). Then, simply mount them at /git (or wherever) and pass whatever information you'd like to git http-backend. For instance, you could retrieve the URI directly via request.uri().as_str().
The pseudocode for something like this is:
fn git_http(req: &Request, _: Data) -> Outcome<'static> {
Outcome::of(git_http_backend(req.method(), req.uri().as_str())
}
fn main() {
let mut git_routes = vec![];
for method in &[Get, Put, Post, Delete, Options, Head, Trace, Connect, Patch] {
git_routes.push(Route::new(*method, "<path..>", git_http));
}
rocket.ignite().mount("/git", git_routes).launch()
}
This is the "unsafe" escape hatch in Rocket. It should rarely, if ever be used, but it's important for cases like yours.
@ndarilek Does this solve your issue?
I believe this has been answered. If you disagree, please comment and we'll revisit the issue. :)
Most helpful comment
This is possible in master with manual routing. The gist of a solution would be to create a
Routeinstance for every HTTP method to the path/<path..>, each pointing to the same handler. In master, if you don't specify a query parameter in the path matcher, then Rocket will match requests with and without a query parameter (see https://github.com/SergioBenitez/Rocket/issues/185#issuecomment-292052648 and 9160483). Then, simply mount them at/git(or wherever) and pass whatever information you'd like togit http-backend. For instance, you could retrieve the URI directly viarequest.uri().as_str().The pseudocode for something like this is:
This is the "unsafe" escape hatch in Rocket. It should rarely, if ever be used, but it's important for cases like yours.