module Strive.Internal.HTTP
( delete
, get
, post
, put
, buildRequest
, performRequest
, handleResponse
, decodeValue
) where
import Data.Aeson (FromJSON, eitherDecode)
import Data.ByteString.Char8 (unpack)
import Data.ByteString.Lazy (ByteString)
import Network.HTTP.Client
(Request, Response, method, parseRequest, responseBody)
import Network.HTTP.Types
( Method
, Query
, QueryLike
, methodDelete
, methodGet
, methodPost
, methodPut
, renderQuery
, toQuery
)
import Strive.Aliases (Result)
import Strive.Client (Client(client_accessToken, client_requester))
delete :: (QueryLike q, FromJSON j) => Client -> String -> q -> IO (Result j)
delete :: Client -> String -> q -> IO (Result j)
delete = Method -> Client -> String -> q -> IO (Result j)
forall q j.
(QueryLike q, FromJSON j) =>
Method -> Client -> String -> q -> IO (Result j)
http Method
methodDelete
get :: (QueryLike q, FromJSON j) => Client -> String -> q -> IO (Result j)
get :: Client -> String -> q -> IO (Result j)
get = Method -> Client -> String -> q -> IO (Result j)
forall q j.
(QueryLike q, FromJSON j) =>
Method -> Client -> String -> q -> IO (Result j)
http Method
methodGet
post :: (QueryLike q, FromJSON j) => Client -> String -> q -> IO (Result j)
post :: Client -> String -> q -> IO (Result j)
post = Method -> Client -> String -> q -> IO (Result j)
forall q j.
(QueryLike q, FromJSON j) =>
Method -> Client -> String -> q -> IO (Result j)
http Method
methodPost
put :: (QueryLike q, FromJSON j) => Client -> String -> q -> IO (Result j)
put :: Client -> String -> q -> IO (Result j)
put = Method -> Client -> String -> q -> IO (Result j)
forall q j.
(QueryLike q, FromJSON j) =>
Method -> Client -> String -> q -> IO (Result j)
http Method
methodPut
http
:: (QueryLike q, FromJSON j)
=> Method
-> Client
-> String
-> q
-> IO (Result j)
http :: Method -> Client -> String -> q -> IO (Result j)
http Method
httpMethod Client
client String
resource q
query = do
Request
request <- Method -> Client -> String -> q -> IO Request
forall q.
QueryLike q =>
Method -> Client -> String -> q -> IO Request
buildRequest Method
httpMethod Client
client String
resource q
query
Response ByteString
response <- Client -> Request -> IO (Response ByteString)
performRequest Client
client Request
request
Result j -> IO (Result j)
forall (m :: * -> *) a. Monad m => a -> m a
return (Response ByteString -> Result j
forall j. FromJSON j => Response ByteString -> Result j
handleResponse Response ByteString
response)
buildRequest :: QueryLike q => Method -> Client -> String -> q -> IO Request
buildRequest :: Method -> Client -> String -> q -> IO Request
buildRequest Method
httpMethod Client
client String
resource q
query = do
Request
request <- String -> IO Request
forall (m :: * -> *). MonadThrow m => String -> m Request
parseRequest (Client -> String -> q -> String
forall q. QueryLike q => Client -> String -> q -> String
buildUrl Client
client String
resource q
query)
Request -> IO Request
forall (m :: * -> *) a. Monad m => a -> m a
return Request
request { method :: Method
method = Method
httpMethod }
buildUrl :: QueryLike q => Client -> String -> q -> String
buildUrl :: Client -> String -> q -> String
buildUrl Client
client String
resource q
query = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ String
"https://www.strava.com/"
, String
resource
, Method -> String
unpack (Bool -> Query -> Method
renderQuery Bool
True (Client -> Query
buildQuery Client
client Query -> Query -> Query
forall a. Semigroup a => a -> a -> a
<> q -> Query
forall a. QueryLike a => a -> Query
toQuery q
query))
]
buildQuery :: Client -> Query
buildQuery :: Client -> Query
buildQuery Client
client = [(String, String)] -> Query
forall a. QueryLike a => a -> Query
toQuery [(String
"access_token", Client -> String
client_accessToken Client
client)]
performRequest :: Client -> Request -> IO (Response ByteString)
performRequest :: Client -> Request -> IO (Response ByteString)
performRequest = Client -> Request -> IO (Response ByteString)
client_requester
handleResponse :: FromJSON j => Response ByteString -> Result j
handleResponse :: Response ByteString -> Result j
handleResponse Response ByteString
response = case Response ByteString -> Either String j
forall j. FromJSON j => Response ByteString -> Either String j
decodeValue Response ByteString
response of
Left String
message -> (Response ByteString, String) -> Result j
forall a b. a -> Either a b
Left (Response ByteString
response, String
message)
Right j
value -> j -> Result j
forall a b. b -> Either a b
Right j
value
decodeValue :: FromJSON j => Response ByteString -> Either String j
decodeValue :: Response ByteString -> Either String j
decodeValue Response ByteString
response = ByteString -> Either String j
forall a. FromJSON a => ByteString -> Either String a
eitherDecode (Response ByteString -> ByteString
forall body. Response body -> body
responseBody Response ByteString
response)