anuragsoni / routes

typed bidirectional router for OCaml/ReasonML web applications
https://anuragsoni.github.io/routes/
BSD 3-Clause "New" or "Revised" License
145 stars 11 forks source link

Optional patterns at the end of path #125

Closed jchavarri closed 3 years ago

jchavarri commented 3 years ago

I have a route that can have the following shapes:

And the same routes with trailing slash.

I am trying to put all of these under a single path. So I defined a pattern for bar and baz, like:

type last =
  | Bar
  | Baz
  | Empty

let last_of_string = function
  | "bar" -> Some Bar
  | "baz" -> Some Baz
  | "" -> Some Empty
  | _ -> None

...

Then I define the path as s "foo" / id / last /? nil);

However, this means that I can't match over foo/:id, but only over foo/:id/, with the trailing slash.

Is it possible to achieve this without defining two paths?

anuragsoni commented 3 years ago

@jchavarri This is indeed a little awkward to deal with with the current API. The current trunk contains support for wildcard matches at the end of the route that might help here. So you would define the route as let route = s "foo" / id /? wildcard. This will need a handler of the form fun (id : id) (rest : string) = .... From your example, the value of rest will be like:

This might be a little nicer than writing multiple routes to get the functionality you need. That said, I think there is room for improvement over what happens with the rest in a wildcard match. I think we can probably represent that with an opaque type Wildcard.t instead of strings so we can represent it in a way that can be used to run a second set of matches without going through a second string split. If you have ideas about how you'd use the wildcard match i'd love to hear them. At the moment the one usecase that was in mind when adding support for this was to dispatch something to a static file handler. So one can add a route like s "static" /? wildcard and forward the wildcard to something that responds with the static content.

jchavarri commented 3 years ago

Yeah, I have tried with wildcard and it works great with the "optionality" part and trailing slashes, but it's too broad for my use case, where all segments are known beforehand.

I will see if I can remove the optionality for now. I guess the building block I'm missing is some kind of helper that allows to either match against nil or a custom pattern at the end of the path 🤔

Thanks!

anuragsoni commented 3 years ago

I guess the building block I'm missing is some kind of helper that allows to either match against nil or a custom pattern at the end of the path thinking

It might be interesting to explore some helpers that make this use-case easier. At the moment the choice between trailing slash vs non trailing slash is explicit via /? vs //?. Maybe there should be a way for someone to define routes that don't care about the trailing slash? And in a similar fashion, we could have a more restrictive version of wildcard where it allows for a user to specify a smaller set of values that should be accepted :thinking: Not sure what the api for that should look like at the moment, but I am not opposed to adding support for this in routes.