Skip to content

Nested routes should backtrack #1890

@parsonsmatt

Description

@parsonsmatt

Suppose you have a route structure like,

[parseRoutes|

/foo FooR
/foo/bar FooBarR
/foo/bar/baz FooBarBazR
 
/foo/other-thing FooOtherThingR

|]

You may want to make the first set a nested route, but not touch the second group for a bit.

[parseRoutes|
/foo FooR:
    /bar FooBarR
    /bar/baz FooBarBazR

/foo/other-thing FooOtherThingR

|]

This route structure is actually semantically different from the first! In the first, if you try to parse /foo/other-thing, first it will try /foo, fail, then try /foo/bar/, fail, then try /foo/bar/baz/, fail, and then finally try /foo/other-thing and succeed. In the second, it will see /foo and commit to FooR. If the FooR route fails to parse, then we get a 404 error, even though /foo/other-thing is a route we should be able to accept.


I think we can get this working pretty easily- we just have to have the helper instead of returning Application, it returns Maybe Application. If Just, then we had a match. If Nothing, then we continue to the next route parse.

Right now, the code generation creates a helper function which has a catch-all match on the route fragment and notFound on it. From -ddump-splices,

                        helperChild0R_adwf _
                          = yesodRunner
                              (Data.Functor.void notFound) env_advU Nothing req_advV

I think, instead, we want to make it return Maybe Application, and then do another pattern guard on that returning Just res. So something like,

instance YesodDispatch App where
    yesodDispatch env req = helper (pathInfo req)
      where
        helper ("foo" : rest) | Just app <- helperFoo rest = app
          where
            helperFoo [] = Just $ yesodRunner ...
            helperFoo ["bar"] = Just $ yesodRunner ...
            helperFoo ["bar", "baz"] = Just $ yesodRunner ...
            helperFoo _ = Nothing
        helper ("foo" : "other-thing" : []) = yesodRunner ...    

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions