Search code examples
haskellihp

Custom route, but keep some routes as the automatic ones


I've added a few Actions on top of the CRUD ones, and I want to have custom routes to the new actions. But still, keep the CRUD actions with the same route (e.g. /ShowPost?postId=[uuid]

instance HasPath PostsController where
    -- ...
    pathTo ShowPostAction { postId } = "/ShowPost?postId=" ++ tshow postId


instance CanRoute PostsController where
   parseRoute' = do
       let posts = do
           string "/Posts"
           optional "/"
           endOfInput
           pure PostsAction

       let showPost = do
           string "/ShowPost?postId="
           postId <- parseId
           optional "/"
           endOfInput
           pure ShowPostAction { postId }


       posts <|> showPosts -- ...

I assume the CanRoute part isn't parsing correctly, as I end up with a 404 page when navigating to /ShowPost?postId=...


Solution

  • The problem here is that the ?postId= is not part of the request path directly as it's part of the query string of the request.

    Given a request like /ShowPost?postId=abc, then the parser input is actually just /ShowPost. The ?postId=abc is available through the ?context variable only.

    You could try something like this (not tested):

    instance HasPath PostsController where
        -- ...
        pathTo ShowPostAction { postId } = "/ShowPost?postId=" ++ tshow postId
    
    -- Define the auto route instance
    instance AutoRoute PostsController
    
    instance CanRoute PostsController where
       parseRoute' = do
           let customRoutes = ...
           customRoutes <|> (autoRoute @PostsController)
    

    Basically this would use your customRoutes parser first and then try to fallback to the parser by AutoRoute.