-- | Helpers for dealing with HTTP requests. module Strive.Internal.HTTP ( delete , get , post , put , buildRequest , performRequest , decodeValue ) where import Data.Aeson (FromJSON, eitherDecode) import Data.ByteString.Char8 (unpack) import Data.ByteString.Lazy (ByteString) import Network.HTTP.Conduit (Request, Response, checkStatus, httpLbs, method, parseUrl, responseBody) import Network.HTTP.Types (Method, Query, QueryLike, methodDelete, methodGet, methodPost, methodPut, renderQuery, toQuery) import Strive.Client (Client (client_accessToken, client_requester)) -- | Perform an HTTP DELETE request. delete :: (QueryLike q, FromJSON j) => Client -> String -> q -> IO (Either String j) delete = http methodDelete -- | Perform an HTTP GET request. get :: (QueryLike q, FromJSON j) => Client -> String -> q -> IO (Either String j) get = http methodGet -- | Perform an HTTP POST request. post :: (QueryLike q, FromJSON j) => Client -> String -> q -> IO (Either String j) post = http methodPost -- | Perform an HTTP PUT request. put :: (QueryLike q, FromJSON j) => Client -> String -> q -> IO (Either String j) put = http methodPut -- | Perform an HTTP request. http :: (QueryLike q, FromJSON j) => Method -> Client -> String -> q -> IO (Either String j) http httpMethod client resource query = do request <- buildRequest httpMethod client resource query response <- performRequest client request return (decodeValue response) -- | Build a request. buildRequest :: QueryLike q => Method -> Client -> String -> q -> IO Request buildRequest httpMethod client resource query = do request <- parseUrl (buildUrl client resource query) return request { checkStatus = \ _ _ _ -> Nothing , method = httpMethod } -- | Build a URL. buildUrl :: QueryLike q => Client -> String -> q -> String buildUrl client resource query = concat [ "https://www.strava.com/" , resource , unpack (renderQuery True (buildQuery client ++ toQuery query)) ] -- | Build a query. buildQuery :: Client -> Query buildQuery client = toQuery [ ("access_token", client_accessToken client) ] -- | Actually perform an HTTP request. performRequest :: Client -> Request -> IO (Response ByteString) performRequest client request = (client_requester client) request -- | Decode a response body as JSON. decodeValue :: FromJSON j => Response ByteString -> Either String j decodeValue response = eitherDecode (responseBody response)