amazonka-core-0.1.1: src/Network/AWS/Response.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeFamilies #-}
-- Module : Network.AWS.Response
-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
-- License : This Source Code Form is subject to the terms of
-- the Mozilla Public License, v. 2.0.
-- A copy of the MPL can be found in the LICENSE file or
-- you can obtain it at http://mozilla.org/MPL/2.0/.
-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
-- Stability : experimental
-- Portability : non-portable (GHC extensions)
module Network.AWS.Response
(
-- * Responses
nullResponse
, headerResponse
, xmlResponse
, xmlHeaderResponse
, jsonResponse
, jsonHeaderResponse
, bodyResponse
) where
import Control.Applicative
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Trans.Resource
import Data.Aeson
import Data.Bifunctor
import qualified Data.ByteString.Lazy as LBS
import Data.Conduit
import qualified Data.Conduit.Binary as Conduit
import Data.Monoid
import Network.AWS.Data (LazyByteString, FromXML(..), decodeXML, build)
import Network.AWS.Types
import Network.HTTP.Client hiding (Request, Response)
import Network.HTTP.Types
import Text.XML (Node)
nullResponse :: (MonadResource m, AWSService (Sv a))
=> Rs a
-> Logger
-> Request a
-> Either HttpException ClientResponse
-> m (Response' a)
nullResponse rs _ = receive $ \_ _ bdy ->
liftResourceT (bdy $$+- return (Right rs))
{-# INLINE nullResponse #-}
headerResponse :: (MonadResource m, AWSService (Sv a))
=> (ResponseHeaders -> Either String (Rs a))
-> Logger
-> Request a
-> Either HttpException ClientResponse
-> m (Response' a)
headerResponse f = deserialise (const (Right ())) (const . f)
{-# INLINE headerResponse #-}
xmlResponse :: (MonadResource m, AWSService (Sv a), FromXML (Rs a))
=> Logger
-> Request a
-> Either HttpException ClientResponse
-> m (Response' a)
xmlResponse = deserialise (decodeXML >=> parseXML) (const Right)
{-# INLINE xmlResponse #-}
xmlHeaderResponse :: (MonadResource m, AWSService (Sv a))
=> (ResponseHeaders -> [Node] -> Either String (Rs a))
-> Logger
-> Request a
-> Either HttpException ClientResponse
-> m (Response' a)
xmlHeaderResponse = deserialise decodeXML
{-# INLINE xmlHeaderResponse #-}
jsonResponse :: (MonadResource m, AWSService (Sv a), FromJSON (Rs a))
=> Logger
-> Request a
-> Either HttpException ClientResponse
-> m (Response' a)
jsonResponse = deserialise eitherDecode' (const Right)
{-# INLINE jsonResponse #-}
jsonHeaderResponse :: (MonadResource m, AWSService (Sv a))
=> (ResponseHeaders -> Object -> Either String (Rs a))
-> Logger
-> Request a
-> Either HttpException ClientResponse
-> m (Response' a)
jsonHeaderResponse = deserialise eitherDecode'
{-# INLINE jsonHeaderResponse #-}
bodyResponse :: (MonadResource m, AWSService (Sv a))
=> (ResponseHeaders -> ResponseBody -> Either String (Rs a))
-> Logger
-> Request a
-> Either HttpException ClientResponse
-> m (Response' a)
bodyResponse f _ = receive $ \a hs bdy ->
return (SerializerError a `first` f hs bdy)
{-# INLINE bodyResponse #-}
deserialise :: (AWSService (Sv a), MonadResource m)
=> (LazyByteString -> Either String b)
-> (ResponseHeaders -> b -> Either String (Rs a))
-> Logger
-> Request a
-> Either HttpException ClientResponse
-> m (Response' a)
deserialise g f l = receive $ \a hs bdy -> do
lbs <- sinkLbs bdy
liftIO $ l Trace ("[Client Response Body]\n" <> build lbs)
return $! case g lbs of
Left e -> Left (SerializerError a e)
Right o ->
case f hs o of
Left e -> Left (SerializerError a e)
Right x -> Right x
{-# INLINE deserialise #-}
receive :: forall m a. (MonadResource m, AWSService (Sv a))
=> (Abbrev -> ResponseHeaders -> ResponseBody -> m (Response a))
-> Request a
-> Either HttpException ClientResponse
-> m (Response' a)
receive f = const (either (return . Left . HttpError) success)
where
success rs = do
let s = responseStatus rs
bdy = responseBody rs
hs = responseHeaders rs
case _svcHandle svc s of
Just g -> Left . g <$> sinkLbs bdy
Nothing -> do
x <- f (_svcAbbrev svc) hs bdy
case x of
Left e -> return (Left e)
Right y -> return $! Right (s, y)
svc = service :: Service (Sv a)
{-# INLINE receive #-}
sinkLbs :: MonadResource m => ResponseBody -> m LBS.ByteString
sinkLbs bdy = liftResourceT (bdy $$+- Conduit.sinkLbs)
{-# INLINE sinkLbs #-}