Add auth support for servant-client

This commit is contained in:
aaron levin 2016-01-09 17:34:27 +01:00
parent 970af450dd
commit ffeeffe745
3 changed files with 57 additions and 0 deletions

View file

@ -27,6 +27,7 @@ source-repository head
library library
exposed-modules: exposed-modules:
Servant.Client Servant.Client
Servant.Common.Auth
Servant.Common.BaseUrl Servant.Common.BaseUrl
Servant.Common.Req Servant.Common.Req
build-depends: build-depends:
@ -34,6 +35,7 @@ library
, aeson , aeson
, attoparsec , attoparsec
, bytestring , bytestring
, base64-bytestring
, exceptions , exceptions
, http-api-data >= 0.1 && < 0.3 , http-api-data >= 0.1 && < 0.3
, http-client , http-client
@ -68,6 +70,7 @@ test-suite spec
, transformers-compat , transformers-compat
, aeson , aeson
, bytestring , bytestring
, base64-bytestring
, deepseq , deepseq
, hspec == 2.* , hspec == 2.*
, http-client , http-client

View file

@ -37,6 +37,7 @@ import Network.HTTP.Media
import qualified Network.HTTP.Types as H import qualified Network.HTTP.Types as H
import qualified Network.HTTP.Types.Header as HTTP import qualified Network.HTTP.Types.Header as HTTP
import Servant.API import Servant.API
import Servant.Common.Auth
import Servant.Common.BaseUrl import Servant.Common.BaseUrl
import Servant.Common.Req import Servant.Common.Req
@ -407,6 +408,21 @@ instance HasClient api => HasClient (IsSecure :> api) where
clientWithRoute Proxy req baseurl manager = clientWithRoute Proxy req baseurl manager =
clientWithRoute (Proxy :: Proxy api) req baseurl manager clientWithRoute (Proxy :: Proxy api) req baseurl manager
instance HasClient api => HasClient (BasicAuth tag realm usr :> api) where
type Client (BasicAuth tag realm usr :> api) = BasicAuthData -> Client api
clientWithRoute Proxy req baseurl manager val =
clientWithRoute (Proxy :: Proxy api) (basicAuthReq val req) baseurl manager
instance ( HasClient api
, AuthenticateClientRequest (AuthProtect tag)
) => HasClient (AuthProtect tag :> api) where
type Client (AuthProtect tag :> api)
= ClientAuthType (AuthProtect tag) -> Client api
clientWithRoute Proxy req baseurl manager val =
clientWithRoute (Proxy :: Proxy api) (authReq val req) baseurl manager
{- Note [Non-Empty Content Types] {- Note [Non-Empty Content Types]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -0,0 +1,38 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE TypeFamilies #-}
-- | Authentication for clients
module Servant.Common.Auth (
AuthenticateClientRequest ( ClientAuthType, authReq )
, BasicAuthData (BasicAuthData, username, password)
, basicAuthReq
) where
import Data.ByteString (ByteString)
import Data.ByteString.Base64 (encode)
import Data.Monoid ((<>))
import Data.Text.Encoding (decodeUtf8)
import Servant.Common.Req (addHeader, Req)
-- | A simple datatype to hold data required to decorate a request
data BasicAuthData = BasicAuthData { username :: ByteString
, password :: ByteString
}
-- | Authenticate a request using Basic Authentication
basicAuthReq :: BasicAuthData -> Req -> Req
basicAuthReq (BasicAuthData user pass) req =
let authText = decodeUtf8 ("Basic " <> encode (user <> ":" <> pass))
in addHeader "Authorization" authText req
-- | Class to represent the ability to authenticate a 'Request'
-- object. For example, we may add special headers to the 'Request'.
class AuthenticateClientRequest a where
data ClientAuthType a :: *
authReq :: ClientAuthType a -> Req -> Req