Extract token from Headers

24 views
Skip to first unread message

Corentin Dupont

unread,
Nov 7, 2018, 12:20:28 PM11/7/18
to haskell...@googlegroups.com
Hello,
I was wondering if there is a way to manipulate headers with Servant.
I have:

newtype Token = Token Text
type API = Header "Authorization" Token :> Get '[JSON] MyData

However, with this method I get "Bearer XXXXX". However, a Token should be only the XXX part...
Any way to extract it automatically?

Thanks
Corentin

erik

unread,
Nov 7, 2018, 12:43:34 PM11/7/18
to corenti...@gmail.com, haskell...@googlegroups.com

--
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/CAEyhvmqsvFmU19wdbmFqJ0EjK1kToAhdt5naOqHP1fZJrD%3D59w%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


--
Erik Aker

Jonathan Jouty

unread,
Nov 8, 2018, 1:09:56 AM11/8/18
to era...@gmail.com, corenti...@gmail.com, haskell...@googlegroups.com
Hi,

Additionally you could implement `FromHttpApiData` using `extractBearerAuth :: ByteString -> Maybe ByteString` from

(or do it yourself if you don't want to depend on `wai-extra`)


For more options, visit https://groups.google.com/d/optout.


--
Jonathan Jouty

Corentin Dupont

unread,
Nov 8, 2018, 4:56:07 AM11/8/18
to era...@gmail.com, haskell...@googlegroups.com
Cool!
So I tried:

data Token = Token Text deriving (Eq, Show)

instance FromHttpApiData KC.Token where
  parseHeader ((stripPrefix "Bearer ") . decodeUtf8 -> Just tok) = Right $ Token tok


However It seems I also need MimeRender (otherwise the function 'serve' complains that there is no instance:

instance MimeRender PlainText KC.Token where
  mimeRender _ (Token tok) = mimeRender PlainText tok


Is this correct?
It complains:
Data constructor not in scope: PlainText :: Proxy ctype0

Where can I find PlainText? I imported Servant.API.ContentTypes to no avail.

Corentin Dupont

unread,
Nov 8, 2018, 5:05:14 AM11/8/18
to era...@gmail.com, haskell...@googlegroups.com
Ok, I managed to solve it this way:

import qualified Data.ByteString.Lazy as BL

instance MimeRender PlainText Token where
  mimeRender _ (Token tok) = BL.fromStrict $ encodeUtf8 tok


Alp Mestanogullari

unread,
Nov 8, 2018, 5:06:52 AM11/8/18
to corenti...@gmail.com, era...@gmail.com, haskell...@googlegroups.com
It should be (Proxy :: Proxy PlainText), not PlainText, in the RHS of the mimeRender definition.

Otherwise, I think you can make Token a newtype of Text and use GeneralizedNewtypeDeriving to get your MimeRender PlainText instance:

newtype Token = Token Text deriving (Eq, Show, MimeRender PlainText)



For more options, visit https://groups.google.com/d/optout.


--
Alp Mestanogullari

Nickolay Kudasov

unread,
Nov 8, 2018, 6:57:04 AM11/8/18
to Alp Mestanogullari, corenti...@gmail.com, era...@gmail.com, haskell...@googlegroups.com
Corentin,

I think it is a bit strange that you're asked to provide MimeRender instance. What is your exact API?

Here's a minimal working Servant server with Token used both in request and response headers:

Kind regards,
Nick

Alp Mestanogullari

unread,
Nov 8, 2018, 8:20:12 AM11/8/18
to Nickolay Kudasov, corenti...@gmail.com, era...@gmail.com, haskell...@googlegroups.com
Nickolay, it's because you're using JSON, whose MimeRender/MimeUnrender instances forward everything to the corresponding aeson classes. While Corentin is using PlainText, which doesn't have any such classes to send everything to. Therefore, you end up having to define MimeRender instances for your user types.


For more options, visit https://groups.google.com/d/optout.


--
Alp Mestanogullari

Corentin Dupont

unread,
Nov 8, 2018, 10:43:03 AM11/8/18
to haskell...@googlegroups.com
Hello again,
is there any plan to support MQTT in Servant?
It's a rather simple protocol that defines PUBLISH and SUBSCRIBE (instead of POST/GET...).

Corentin Dupont

unread,
Nov 8, 2018, 10:43:37 AM11/8/18
to nickolay...@gmail.com, alpm...@gmail.com, era...@gmail.com, haskell...@googlegroups.com
Thanks a lot for your example, it is working now.

On Thu, Nov 8, 2018 at 12:57 PM Nickolay Kudasov <nickolay...@gmail.com> wrote:

Arian van Putten

unread,
Nov 8, 2018, 11:25:03 AM11/8/18
to haskell...@googlegroups.com
And to the group. I forgot to hit reply all :)

---------- Forwarded message ---------
From: Arian van Putten <aero...@gmail.com>
Date: Thu, Nov 8, 2018 at 5:24 PM
Subject: Re: MQTT
To: Corentin Dupont <corenti...@gmail.com>


Hey,
Brining more types to IoT seems like a cool idea :)

Here are just some quick thoughts by me googling about MQTT:

A quick glance at the standard, MQTT seems to be not an extension to HTTP (http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html) . It runs on top of TCP/IP,  just like HTTP, it has topics, similar to URLs in HTTP,
but the similarities seem to stop there.. For example, there doesn't seem to be any notion of content types of requests and responses, whilst content negotiation is one of the core features of Servant (in my opinion).
Because MQTT doesn't have this notion, I'm not sure how one would implement type-directed routing ala Servant. You would have to implement some notion of content types on top of MQTT, but that would perhaps make
it hard to interact with existing MQTT implementations.   Do you know if there are standard extensions that add this kind of functionality?

Secondly, from a glance, MQTT seems to be a very bi-directional protocol that supports many to many communication, whilst HTTP (and servant) is very client-server oriented.

I'm sure there is merit in doing a typed (servant-like) approach to MQTT topics, but I'm not sure if putting it in servant is the right approach. Given the very different natures of these protocols.
However, I do think the type-level DSL could be re-used to write
type-level MQTT topics, and I also think looking at the servant routing implementation (or this blog post https://www.well-typed.com/blog/2015/11/implementing-a-minimal-version-of-haskell-servant/) could
give a good idea how to implement a MQTT-based router for such a DSL.


If you have any questions for  implementing such a router yourself, feel free to ask them here, or poke me on IRC (#servant, arianvp).

--
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.

For more options, visit https://groups.google.com/d/optout.


--
Groetjes,

Arian

Nickolay Kudasov

unread,
Nov 8, 2018, 2:16:23 PM11/8/18
to Corentin Dupont, alpm...@gmail.com, era...@gmail.com, haskell...@googlegroups.com
Alp,

Ah, I see, that makes sense now :)

Corentin, glad I was able to help anyway!

Kind regards,
Nick

Reply all
Reply to author
Forward
0 new messages