a FromSegments that works in the middle of the path
Yes, I know why this isn't as straightforward as it first appears.
- Why you believe this feature is necessary.
Strictly it's not necessary, but it would be rather nice since a lot of APIs in the wild go mad on how they use urls and it would make porting them to rust much easier.
- A convincing use-case for this feature.
Implementing e.g. the docker registry HTTP API which permits an arbitrary number of segments in the middle of the path to name the repository. Here are some examples:
/v2/foo/manifests/<ref> => foo
/v2/foo/bar/manifests/<ref> => foo/bar
/v2/foo/bar/baz/manifests/<ref> => foo/bar/baz
- Why this feature can't or shouldn't exist outside of Rocket.
It could, but since it's useful for implementing a variety of in-the-wild apis compatibly, it would be nice to have it in core to allow people to just quickly port them. Doing it currently is ugly in the extreme.
Yes! We should make this happen. What's the syntax? Should the following work as expected?
#[get("/v2/<repo..>/manifests/<ref>")]
fn handler(repo: Repository, ref: Ref) -> T {
...
}
// Repository: FromSegments
// Ref: FromParam
I think reusing the existing syntax would be perfect.
The major difficulty i think we might have is that the user could conceivably construct routes that don't allow for an unambiguous route choice. Obviously as we are running at compile time, we can flag this to the user, but first we must detect it.
FWIW I have exactly this issue at the minute. I just went with the temporary fix of allowing exactly 1 to 3 levels of naming: https://github.com/ContainerSolutions/trow/blob/master/src/routes.rs#L125
Fixing this would make my life better. And the suggestion seems fine to me.
Fair point about overlapping routes. This could be detected and disallowed, but another, possibly simpler choice would be to allow controlling precedence in routes (if it doesn't match a, then try b etc).
We'll make this happen by v0.5. @amouat Note that "ranking" already controls precedence.
We won't get this in by 0.5, sadly. Pushing to 0.6.
I tried to work on this but it's hard (I've never written any proc_macro). Here are the required steps I see for a PR:
- remove the EarlyTrailing error here
- update the route matching here
- change the handling of the "trailing" attribute a bit everywhere (e.g.)
- Finally, the hard part: update
param_guard_declandcodegen_route
I'm stuck at updating param_guard_decl
Yes, this is a very hard change to make. It would require at least:
- Changing or checking every place that checks/assumes that a dynamic trailing parameter (i.e,
<foo..>) is at the end of a path. That includes collision checking incollider.rs, matching inmatcher.rs, codegen, and maybe others. - Understanding rules for and disallowing nonsensical routes like
/a/<b..>/<c..>That is, understanding and codifying what<a..>in the middle of a path really means. Can it be empty? Do/a/<b..>/cand/a/ccollide? Is/a/<b..>/c/<d..>allowed? What about/a/<b..>/<c>? - Changing collision checking so that things like
/a/<b..>/cand/a/b/<c..>/ccollide. - Changing route matching so routes are matched as expected.
- Changing internal raw segments getters to take this into account.
- Changing code generation so that it uses the internal raw segments methods correctly.
- Changing
FromSegmentsimplementations to take this into account, if needed. - Fixing every relevant test.
- Running the collision-matcher fuzzer for as long as possible to try to revalidate collision safety.