git.iko.soy/typeable/servant
on master help sign in
add Servant.API.Header
501dafaAlp Mestanogullari
servant.cabal+1
@@ -105,6 +105,7 @@ library
105 Servant.API.Capture
105 Servant.API.Capture
106 Servant.API.Delete
106 Servant.API.Delete
107 Servant.API.Get
107 Servant.API.Get
108+ Servant.API.Header
108 Servant.API.Post
109 Servant.API.Post
109 Servant.API.Put
110 Servant.API.Put
110 Servant.API.QueryParam
111 Servant.API.QueryParam
src/Servant/API.hs+3
@@ -9,6 +9,8 @@ module Servant.API (
9 -- * Accessing information from the request
9 -- * Accessing information from the request
10 -- | Capturing parts of the url path as parsed values: @'Capture'@
10 -- | Capturing parts of the url path as parsed values: @'Capture'@
11 module Servant.API.Capture,
11 module Servant.API.Capture,
12+ -- | Retrieving specific headers from the request
13+ module Servant.API.Header,
12 -- | Retrieving parameters from the query string of the 'URI': @'QueryParam'@
14 -- | Retrieving parameters from the query string of the 'URI': @'QueryParam'@
13 module Servant.API.QueryParam,
15 module Servant.API.QueryParam,
14 -- | Accessing the request body as a JSON-encoded type: @'ReqBody'@
16 -- | Accessing the request body as a JSON-encoded type: @'ReqBody'@
@@ -40,6 +42,7 @@ import Servant.API.Alternative
40import Servant.API.Capture
42import Servant.API.Capture
41import Servant.API.Delete
43import Servant.API.Delete
42import Servant.API.Get
44import Servant.API.Get
45+import Servant.API.Header
43import Servant.API.Post
46import Servant.API.Post
44import Servant.API.Put
47import Servant.API.Put
45import Servant.API.QueryParam
48import Servant.API.QueryParam
src/Servant/API/Header.hsnew file+58
@@ -0,0 +1,58 @@
1+{-# LANGUAGE PolyKinds #-}
2+{-# LANGUAGE TypeFamilies #-}
3+{-# LANGUAGE TypeOperators #-}
4+{-# LANGUAGE FlexibleInstances #-}
5+{-# LANGUAGE ScopedTypeVariables #-}
6+module Servant.API.Header where
7+
8+import Data.Proxy
9+import Data.String
10+import Data.Text.Encoding (decodeUtf8)
11+import GHC.TypeLits
12+import Network.Wai
13+import Servant.API.Sub
14+import Servant.Common.Text
15+import Servant.Server
16+
17+-- | Extract the given header's value as a value of type @a@.
18+--
19+-- Example:
20+--
21+-- > newtype Referer = Referer Text
22+-- > deriving (Eq, Show, FromText, ToText)
23+-- >
24+-- > -- GET /view-my-referer
25+-- > type MyApi = "view-my-referer" :> Header "from" Referer :> Get Referer
26+data Header sym a
27+
28+-- | If you use 'Header' in one of the endpoints for your API,
29+-- this automatically requires your server-side handler to be a function
30+-- that takes an argument of the type specified by 'Header'.
31+-- This lets servant worry about extracting it from the request and turning
32+-- it into a value of the type you specify.
33+--
34+-- All it asks is for a 'FromText' instance.
35+--
36+-- Example:
37+--
38+-- > newtype Referer = Referer Text
39+-- > deriving (Eq, Show, FromText, ToText)
40+-- >
41+-- > -- GET /view-my-referer
42+-- > type MyApi = "view-my-referer" :> Header "Referer" Referer :> Get Referer
43+-- >
44+-- > server :: Server MyApi
45+-- > server = viewReferer
46+-- > where viewReferer :: Referer -> EitherT (Int, String) IO referer
47+-- > viewReferer referer = return referer
48+instance (KnownSymbol sym, FromText a, HasServer sublayout)
49+ => HasServer (Header sym a :> sublayout) where
50+
51+ type Server (Header sym a :> sublayout) =
52+ Maybe a -> Server sublayout
53+
54+ route Proxy subserver request respond = do
55+ let mheader = fromText . decodeUtf8 =<< lookup str (requestHeaders request)
56+ route (Proxy :: Proxy sublayout) (subserver mheader) request respond
57+
58+ where str = fromString $ symbolVal (Proxy :: Proxy sym)