Happstack, Yesod

68 views
Skip to first unread message

Corentin Dupont

unread,
May 10, 2016, 8:47:12 AM5/10/16
to haskell...@googlegroups.com
Hi guys,
can I use servant with Happstack?
My app is currently built with Happstack, so it would be nice to handle the REST API also with it.
It seems there is only an alpha release now, right?
And what about Yesod? Is it supported?
Thanks,
Corentin

Julian Arni

unread,
May 10, 2016, 9:18:07 AM5/10/16
to Corentin Dupont, haskell-servant
With Yesod it's fairly easy - you can just use the `Raw` combinator

type MyAPI = ServantAPI :<|> "yesod" :> Raw

myServer :: Server MyAPI
myServer = servantServer :<|> toWaiApp ...

With Happstack, servant-happstack is an option (though then you would not be able to use the above method for Yesod, I believe).

Alternatively, you can just proxy the requests to the other frameworks, either by (a) having a proxy server that dispatches to either servant or the other framework based on route or headers or whatever it is, or (b) having one of the servant routes use a proxy (e.g., http-proxy [0]), and again use Raw. (a) is a pretty common technique generally.

[0] https://hackage.haskell.org/package/http-proxy

--
You received this message because you are subscribed to the Google Groups "haskell-servant" group.
To unsubscribe from this group and stop receiving emails from it, send an email to haskell-serva...@googlegroups.com.
To post to this group, send email to haskell...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/haskell-servant/CAEyhvmo5wub_YCw48q2ijEXHpPguinLgD-W%3D83O-pyqpnY6yag%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Corentin Dupont

unread,
May 10, 2016, 9:29:44 AM5/10/16
to Julian Arni, haskell-servant
Do you know when it will be released?

Julian Arni

unread,
May 10, 2016, 9:49:00 AM5/10/16
to Corentin Dupont, haskell-servant
Nope... the initial work was done by Jeremy Shaw, but someone would have to take over the task of merging it (which involves refactoring some of the common logic, and which relates to work that Greg Hale did with servant-snap). I don't know if anyone is working on that though.

Corentin Dupont

unread,
May 10, 2016, 2:21:53 PM5/10/16
to Julian Arni, haskell-servant, ha...@googlegroups.com, Jeremy Shaw

OK... I also use happstack-authenticate for authentication of my website. Can it be used with servant?
I'm not sure if happstack-authenticate can use the auth token in the HTTP header.

In general, how and where do you retrieve an auth token? Should I retrieve from happstack-authenticate?
I found this:
https://hackage.haskell.org/package/happstack-authenticate-2.3.4/docs/src/Happstack-Authenticate-Core.html#getToken
is this the token I should put in the header when making an API request?

Corentin Dupont

unread,
May 12, 2016, 2:18:16 PM5/12/16
to Julian Arni, haskell-servant
Hi again guys,
is there some resource for using authentication with Yesod and Servant?
Thanks

Julian Arni

unread,
May 13, 2016, 7:18:54 AM5/13/16
to Corentin Dupont, haskell-servant
On Thu, May 12, 2016 at 8:18 PM, Corentin Dupont <corenti...@gmail.com> wrote:
Hi again guys,
is there some resource for using authentication with Yesod and Servant?

I don't think anyone has blogged about it. But how are those two connected? If in the same Application, you can use authentication/session Middleware, and it'll just work for both.
 

Yann Esposito

unread,
May 13, 2016, 3:21:10 PM5/13/16
to haskell-servant, corenti...@gmail.com
Actually I'm using a Yesod application which use their plugin system for authentication.
Here is some working code:

~~~~
import Data.CaseInsensitive (CI)

identityHeaderName :: CI ByteString
identityHeaderName = "Yesod-Identity"

addQueryId :: Maybe ByteString -> W.Request -> W.Request
addQueryId identity req =
  let f = maybe id (\x hs -> (identityHeaderName,x):hs) identity
  in req {W.requestHeaders = f (W.requestHeaders req)}

removeIdentityQuery :: W.Request -> W.Request
removeIdentityQuery req = req {
  W.requestHeaders = filter ((/= identityHeaderName) . fst)
                            (W.requestHeaders req)
  }

addIdentity :: Maybe ByteString -> Middleware
addIdentity identity app req sendResp =
  let req' = removeIdentityQuery req
      req'' = addQueryId identity req'
  in
    app req'' sendResp

addIdentity :: Maybe ByteString -> Middleware
addIdentity identity app req sendResp =
  let req' = removeIdentityQuery req
      req'' = addQueryId identity req'
  in
    app req'' sendResp

followToApp :: Handler TypedContent
followToApp = do
  app <- getYesod
  auth <- maybeAuth
  let identity = case auth of
                      Just (Entity _ u) -> Just (encodeUtf8 (userIdent u))
                      Nothing -> Nothing
  print identity
  sendWaiApplication (addIdentity identity (appREST app))

getHomeR :: Texts -> Handler TypedContent
getHomeR _ = followToApp

postHomeR :: Texts -> Handler TypedContent
postHomeR _ = followToApp
~~~~

and I had to put this in config/routes:

~~~
!/*Texts HomeR GET POST
~~~

The `appREST` is the WAI application returned by Servant that I initialise in Foundation.hs.
I added `appREST` field of type Application in the App record.
Reply all
Reply to author
Forward
0 new messages