Search code examples
haskellhaskell-snap-frameworkreflex

How to properly do nested routing in Obelisk?


I have been searching for examples, however most examples do a RouteSomething -> PathSegment "firstpath" $ unitEncoder mempty and not a single nested route.

There are some examples that use Cat.id to pass the whole URI as a Text such Characher-Sheet:

backendRouteEncoder = mkFullRouteEncoder
  (FullRoute_Backend BackendRoute_Missing :/ ())
  (\case
    BackendRoute_API -> PathSegment "api" $ Cat.id
    BackendRoute_Missing -> PathSegment "missing" $ unitEncoder mempty
  )

and then on the backend parse the whole route:

server sql (BackendRoute_API :=> Identity _) = dir "api" $
    route [ ("spelllist/", runReaderT spellListHandler sql)
          , ("featlist/", runReaderT featListHandler sql)
          ]

however, this feels odd since I would have thought all routing would have been defined in Common.Route with Obelisk.Route as per the skeleton of ob init and other examples defining routes exclusively there. I would appreciate the safety of exhaustiveness check of the LambdaCase over the datatype codifying routes and not having to add BackendRoute_Missing equivalent on all possible backend/frontend subroutes.


Solution

  • data FrontendRoute :: * -> * where
      FrontendRoute_Sub :: FrontendRoute (R SubRoute)
    data SubRoute :: * -> * where
      SubRoute_Foo :: SubRoute ()
    

    Then replace unitEncoder with pathComponentEncoder $ \case ...

    See obelisk-oauth for another example.