module Network.HTTP.Client.Contrib where

import Data.Aeson
import Data.Bifunctor
import Data.ByteString.Lazy.Char8 qualified as BSL
import Network.HTTP.Conduit
import Network.HTTP.Types qualified as HT

-- | Get response body out of a @Response@
handleResponse :: Response BSL.ByteString -> Either BSL.ByteString BSL.ByteString
handleResponse :: Response ByteString -> Either ByteString ByteString
handleResponse Response ByteString
rsp
  | Status -> Bool
HT.statusIsSuccessful (Response ByteString -> Status
forall body. Response body -> Status
responseStatus Response ByteString
rsp) = ByteString -> Either ByteString ByteString
forall a b. b -> Either a b
Right (Response ByteString -> ByteString
forall body. Response body -> body
responseBody Response ByteString
rsp)
  -- TODO: better to surface up entire resp so that client can decide what to do when error happens.
  -- e.g. when 404, the response body could be empty hence library user has no idea what's happening.
  -- Which will be breaking changes.
  -- The current work around is surface up entire response as string.
  | ByteString -> Bool
BSL.null (Response ByteString -> ByteString
forall body. Response body -> body
responseBody Response ByteString
rsp) = ByteString -> Either ByteString ByteString
forall a b. a -> Either a b
Left ([Char] -> ByteString
BSL.pack ([Char] -> ByteString) -> [Char] -> ByteString
forall a b. (a -> b) -> a -> b
$ Response ByteString -> [Char]
forall a. Show a => a -> [Char]
show Response ByteString
rsp)
  | Bool
otherwise = ByteString -> Either ByteString ByteString
forall a b. a -> Either a b
Left (Response ByteString -> ByteString
forall body. Response body -> body
responseBody Response ByteString
rsp)

handleResponseJSON ::
  FromJSON a =>
  Response BSL.ByteString ->
  Either BSL.ByteString a
handleResponseJSON :: forall a. FromJSON a => Response ByteString -> Either ByteString a
handleResponseJSON =
  (ByteString -> Either ByteString a)
-> (ByteString -> Either ByteString a)
-> Either ByteString ByteString
-> Either ByteString a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ByteString -> Either ByteString a
forall a b. a -> Either a b
Left (([Char] -> ByteString) -> Either [Char] a -> Either ByteString a
forall a b c. (a -> b) -> Either a c -> Either b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first [Char] -> ByteString
BSL.pack (Either [Char] a -> Either ByteString a)
-> (ByteString -> Either [Char] a)
-> ByteString
-> Either ByteString a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either [Char] a
forall a. FromJSON a => ByteString -> Either [Char] a
eitherDecode) (Either ByteString ByteString -> Either ByteString a)
-> (Response ByteString -> Either ByteString ByteString)
-> Response ByteString
-> Either ByteString a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Response ByteString -> Either ByteString ByteString
handleResponse