{-# LANGUAGE FlexibleContexts #-}
module Network.Livy.Response
(
send
) where
import Control.Lens
import Control.Monad.Catch
import Control.Monad.Reader
import Data.Aeson
import qualified Data.ByteString as S
import qualified Data.ByteString.Char8 as C
import qualified Data.ByteString.Lazy as LBS
import Network.HTTP.Client
import Network.HTTP.Types
import Network.Livy.Env
import Network.Livy.Monad
import Network.Livy.Request
import Network.Livy.Types
send :: LivyConstraint r m a => a -> m (Either LivyError (LivyResponse a))
send req = do
env <- reader $ view environment
catch (handleRequest req env) handleHttpException
handleRequest
:: (MonadIO m, LivyRequest b, FromJSON a)
=> b
-> Env
-> m (Either LivyError a)
handleRequest req env = liftIO $ httpLbs req' man >>= handleResponse
where
man = env ^. envManager
req' = request req & setHost (env ^. envHost) & setPort (env ^. envPort)
handleResponse
:: (Applicative m, FromJSON a)
=> Response LBS.ByteString
-> m (Either LivyError a)
handleResponse resp =
if livyHttpError (responseStatus resp) then pure . Left $
makeLivyHttpError (sCode resp) (sMessage resp) (responseBody resp)
else pure $ parseResponse resp
where
sCode = statusCode . responseStatus
sMessage = statusMessage . responseStatus
parseResponse :: FromJSON a => Response LBS.ByteString -> Either LivyError a
parseResponse resp = case eitherDecode' (responseBody resp) of
Left e -> Left $ LivyError ParseFailure (C.pack e) Nothing Nothing
Right v -> Right v
handleHttpException
:: Applicative m
=> HttpException
-> m (Either LivyError a)
handleHttpException e = pure . Left $ LivyError
(LibraryException e) "Exception generated by http-client" Nothing Nothing
livyHttpError :: Status -> Bool
livyHttpError s = statusCode s >= 400
makeLivyHttpError
:: Int
-> S.ByteString
-> LBS.ByteString
-> LivyError
makeLivyHttpError c m b = LivyError InvalidRequest m (Just b) $
case c of
400 -> Just BadRequest
401 -> Just Unauthorized
402 -> Just RequestFailed
403 -> Just Forbidden
404 -> Just NotFound
405 -> Just BadMethod
500 -> Just ServerError
501 -> Just ServerError
502 -> Just ServerError
503 -> Just ServerError
504 -> Just ServerError
_ -> Just UnknownHTTPErrorCode