I am following this tutorial http://www.parsonsmatt.org/programming/2015/06/07/servant-persistent.html to create APIs through servant. I want to customize the server to serve static files as well but couldn't find a way to do it.
I am using the stack
build tool.
I modified the Main.hs
file's run to include static
(run port $ static $ logger $ app cfg
) and I imported Network.Wai.Middleware.Static (static)
. I also added wai-middleware-static >=0.7.0 && < 0.71
to my cabal file.
When I run (Update: This part is totally my error. I added the the package to the wrong cabal file.. lame. Importing Network.Wai.Middleware.Static works and serves static files. Leaving the error below in case anyone searches for it and finds it useful.)stack build
I get:
Could not find module ‘Network.Wai.Middleware.Static’
Perhaps you meant
Network.Wai.Middleware.Gzip (from wai-extra-3.0.7.1@waiex_GpotceEdscHD6hq9p0wPOJ)
Network.Wai.Middleware.Jsonp (from wai-extra-3.0.7.1@waiex_GpotceEdscHD6hq9p0wPOJ)
Network.Wai.Middleware.Local (from wai-extra-3.0.7.1@waiex_GpotceEdscHD6hq9p0wPOJ)
Next I tried using servant's serveDirectory
as follows (simplified):
type API = "users" :> Get '[JSON] [Person]
:<|> "static" :> Raw
server = createPerson :<|> serveDirectory "/static"
I get this error:
Couldn't match type ‘IO’ with ‘EitherT ServantErr IO’
arising from a functional dependency between:
constraint ‘Servant.Server.Internal.Enter.Enter
(IO Network.Wai.Internal.ResponseReceived)
(AppM :~> EitherT ServantErr IO)
(IO Network.Wai.Internal.ResponseReceived)’
arising from a use of ‘enter’
instance ‘Servant.Server.Internal.Enter.Enter
(m a) (m :~> n) (n a)’
at <no location info>
In the expression: enter (readerToEither cfg) server
In an equation for ‘readerServer’:
readerServer cfg = enter (readerToEither cfg) server
I am a Haskell beginner and I am not familiar with Wai so unsure where to even begin. What changes do I need to make the example code in the Blog post to serve static files?
Edit: Since the comments get hidden from the default view, I am pasting my last comment here:
Here is toned down version of Matt's code from his blog. I consolidated all his modules into a single file, removed all the database stuff but did not clean up the extensions/imports. When I run this code I get the above type mismatch error. Please note that this code does not use Network.Wai.Middleware.Static and I am using qualified import of Servant StaticFiles.
Thanks!
wai-app-static
in that context. – Ecogniumenter
machinery converts your handlers from some monad to another. YourReader
-based server has aRaw
in it for file serving, soenter
tries to convert the file-serving thing fromReaderT ...
toEitherT ...
, which won't work becauseserveDirectory
doesn't live inReaderT
. I'm not sure if this is a bug in servant or if it's really more meaningful to define the file-serving handler separately, apart from all theReaderT
ones. I have notified the other servant devs. In the meantime. – Alp Mestanogullari