module Network.OAuth2.HTTP.HttpClient
( requestAccessToken
, doRequest
, signRequest
) where
import Control.Monad.Trans.Resource
import Data.Aeson
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import Data.List
import Data.Maybe
import Network.HTTP.Types (renderSimpleQuery, parseSimpleQuery)
import qualified Network.HTTP.Types as HT
import Network.HTTP.Conduit
import Control.Exception
import Control.Applicative ((<$>))
import Network.OAuth2.OAuth2
requestAccessToken :: OAuth2
-> BS.ByteString
-> IO (Maybe AccessToken)
requestAccessToken oa code = decode <$> requestAccessToken' oa code
requestAccessToken' :: OAuth2 -> BS.ByteString -> IO BSL.ByteString
requestAccessToken' oa code = doRequest req >>= retOrError
where
req = urlEncodedBody body $ toReq' uri
(uri, body) = accessTokenUrl oa code
retOrError rsp = if (HT.statusCode . statusCode) rsp == 200
then return $ responseBody rsp
else throwIO . OAuthException $ "Gaining access_token failed: " ++ BSL.unpack (responseBody rsp)
signRequest :: OAuth2 -> Request m -> Request m
signRequest oa req = req { queryString = renderSimpleQuery False newQuery }
where
newQuery = case oauthAccessToken oa of
Just at -> insert ("access_token", at) oldQuery
_ -> insert ("client_id", oauthClientId oa) . insert ("client_secret", oauthClientSecret oa) $ oldQuery
oldQuery = parseSimpleQuery (queryString req)
toReq' :: BS.ByteString -> Request a
toReq' = fromJust . parseUrl . BS.unpack
doRequest :: ResourceIO m => Request m -> m (Response BSL.ByteString)
doRequest = withManager . httpLbs