serveDirectory + custom monad does not work - what's the alternative?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

serveDirectory + custom monad does not work - what's the alternative?

James Wilson
I have defined some routes, and I'd like to fall through to serving static content if none of those routes match. Form the docs, it looks like the answer is

type Routes = MyRoutes :<|> ... :<|> Raw
handlers    
= myRoutes :<|> ... :<|> serveDirectory "some-directory"

However, this does not work when I have also used a custom Monad, and so my main method looks a little like:

 let handlers = enter (appToHandler appState) routes
 let context = hasSessionHandler appState :. isAdminHandler appState :. EmptyContext
 let server = serveWithContext (Proxy :: Proxy Routes) context handlers

 run 8080 server

It turns out that this is referenced in several Github issues for Servant stretching back a while, but it looks like no solution has been agreed upon.

So my question is; what is the standard approach to serving a directory of static files alongside my servant routes when I use a custom monad?

The only approach that comes to mind so far is to not use a custom monad, and instead thread my state through to each route and jump into a custom monad per-route instead. I'd love to hear if there is a better approach!

--
Reply | Threaded
Open this post in threaded view
|

Re: serveDirectory + custom monad does not work - what's the alternative?

James Wilson
After a bit more reading I bumped into http://stackoverflow.com/questions/31020207/serving-static-files-with-servant-wai (which I saw before but didn't spot that it was the answer I was looking for!)

Basically, the solution is simply to call "enter" only on the custom monad routes, and to keep the serveDirectory route separate. The above code snippet becomes:

let handlers = enter (appToHandler appState) routes :<|> serveDirectory staticDir
let context = hasSessionHandler appState :. isAdminHandler appState :. EmptyContext
let server
= serveWithContext (Proxy :: Proxy (Routes :<|> Raw)) context handlers

run
8080 server

Noting that we add the serveDirectory route separately from the routes that we call enter on (and add a corresponding Raw to the typed routes), and everything seems to work :)

--