module Web.Hyperpublic.Internal
( callApi
) where
import Data.Aeson ( Value
, json )
import Data.Attoparsec ( eitherResult
, parse )
import Data.ByteString ( ByteString
, append )
import Data.ByteString.Char8 ( unpack )
import qualified Data.ByteString.Lazy as Lazy
import Network.HTTP.Enumerator ( Request (..)
, Response (..)
, def
, httpLbsRedirect
, withManager )
import Network.HTTP.Types ( SimpleQuery
, StdMethod (..)
, renderStdMethod
, simpleQueryToQuery )
import Web.Hyperpublic
callApi :: HpAuth -> StdMethod -> ByteString -> SimpleQuery -> IO Value
callApi auth mthd urlPath query = do
let query' = [ ("client_id", clientId auth)
, ("client_secret", clientSecret auth) ] ++
filter cleanQuery query
rsp <- withManager (httpLbsRedirect $ request mthd urlPath query')
eitherToIO $ Right rsp >>= readResponse >>= eitherResult . parse json
where
cleanQuery (k, _) = k /= "client_id" && k /= "client_secret"
request :: StdMethod -> ByteString -> SimpleQuery -> Request m
request mthd urlPath query = def
{ method = renderStdMethod mthd
, host = "api.hyperpublic.com"
, path = "/api/v1" `append` urlPath
, queryString = simpleQueryToQuery query
, port = 443
, secure = True }
readResponse :: Response -> Either String ByteString
readResponse rsp =
let strictBody = foldr1 append $ Lazy.toChunks $ responseBody rsp
in if statusCode rsp == 200
then Right strictBody
else Left $ show (statusCode rsp) ++ ": " ++ unpack strictBody
eitherToIO :: Either String a -> IO a
eitherToIO (Right a) = return a
eitherToIO (Left str) = fail str