@@ -21,7 +21,7 @@ import Data.Proxy
2121import Data.String.Conversions
2222import Data.Text (unpack)
2323import GHC.TypeLits
24−import Network.HTTP.Types
24+import qualified Network.HTTP.Types as H
2525import Servant.API
2626import Servant.Common.BaseUrl
2727import Servant.Common.Req
@@ -108,7 +108,7 @@ instance HasClient Delete where
108108 type Client Delete = BaseUrl -> EitherT String IO ()
109109
110110 clientWithRoute Proxy req host =
111− performRequestJSON methodDelete req 204 host
111+ performRequestJSON H.methodDelete req 204 host
112112
113113-- | If you have a 'Get' endpoint in your API, the client
114114-- side querying function that is created when calling 'client'
@@ -117,7 +117,44 @@ instance HasClient Delete where
117117instance FromJSON result => HasClient (Get result) where
118118 type Client (Get result) = BaseUrl -> EitherT String IO result
119119 clientWithRoute Proxy req host =
120− performRequestJSON methodGet req 200 host
120+ performRequestJSON H.methodGet req 200 host
121+
122+-- | If you use a 'Header' in one of your endpoints in your API,
123+-- the corresponding querying function will automatically take
124+-- an additional argument of the type specified by your 'Header',
125+-- wrapped in Maybe.
126+--
127+-- That function will take care of encoding this argument as Text
128+-- in the request headers.
129+--
130+-- All you need is for your type to have a 'ToText' instance.
131+--
132+-- Example:
133+--
134+-- > newtype Referer = Referer Text
135+-- > deriving (Eq, Show, FromText, ToText)
136+-- >
137+-- > -- GET /view-my-referer
138+-- > type MyApi = "view-my-referer" :> Header "Referer" Referer :> Get Referer
139+-- >
140+-- > myApi :: Proxy MyApi
141+-- > myApi = Proxy
142+-- >
143+-- > viewReferer :: Maybe Referer -> BaseUrl -> EitherT String IO Book
144+-- > viewReferer = client myApi
145+-- > -- then you can just use "viewRefer" to query that endpoint
146+-- > -- specifying Nothing or Just "http://haskell.org/" as arguments
147+instance (KnownSymbol sym, ToText a, HasClient sublayout)
148+ => HasClient (Header sym a :> sublayout) where
149+
150+ type Client (Header sym a :> sublayout) =
151+ Maybe a -> Client sublayout
152+
153+ clientWithRoute Proxy req mval =
154+ clientWithRoute (Proxy :: Proxy sublayout) $
155+ maybe req (\value -> addHeader hname value req) mval
156+
157+ where hname = symbolVal (Proxy :: Proxy sym)
121158
122159-- | If you have a 'Post' endpoint in your API, the client
123160-- side querying function that is created when calling 'client'
@@ -127,7 +164,7 @@ instance FromJSON a => HasClient (Post a) where
127164 type Client (Post a) = BaseUrl -> EitherT String IO a
128165
129166 clientWithRoute Proxy req uri =
130− performRequestJSON methodPost req 201 uri
167+ performRequestJSON H.methodPost req 201 uri
131168
132169-- | If you have a 'Put' endpoint in your API, the client
133170-- side querying function that is created when calling 'client'
@@ -137,7 +174,7 @@ instance FromJSON a => HasClient (Put a) where
137174 type Client (Put a) = BaseUrl -> EitherT String IO a
138175
139176 clientWithRoute Proxy req host =
140− performRequestJSON methodPut req 200 host
177+ performRequestJSON H.methodPut req 200 host
141178
142179-- | If you use a 'QueryParam' in one of your endpoints in your API,
143180-- the corresponding querying function will automatically take
@@ -258,7 +295,7 @@ instance (KnownSymbol sym, HasClient sublayout)
258295-- | Pick a 'Method' and specify where the server you want to query is. You get
259296-- back the status code and the response body as a 'ByteString'.
260297instance HasClient Raw where
261− type Client Raw = Method -> BaseUrl -> EitherT String IO (Int, ByteString)
298+ type Client Raw = H.Method -> BaseUrl -> EitherT String IO (Int, ByteString)
262299
263300 clientWithRoute :: Proxy Raw -> Req -> Client Raw
264301 clientWithRoute Proxy req httpMethod host =