@@ -18,35 +18,48 @@ import Control.Arrow
18import Control.Concurrent
18import Control.Concurrent
19import Control.Exception
19import Control.Exception
20import Control.Monad
20import Control.Monad
21−import Control.Monad.Base (MonadBase (..))
21+import Control.Monad.Base
22−import Control.Monad.Catch (MonadCatch, MonadThrow)
23+import Control.Monad.Catch
24+ (MonadCatch, MonadThrow)
23−import Control.Monad.Error.Class (MonadError (..))
25+import Control.Monad.Error.Class
24import Control.Monad.Reader
27import Control.Monad.Reader
25−import Control.Monad.Trans.Control (MonadBaseControl (..))
28+import Control.Monad.Trans.Control
29+ (MonadBaseControl (..))
26import Control.Monad.Trans.Except
30import Control.Monad.Trans.Except
33+import Data.ByteString.Builder
27−import Data.ByteString.Builder (toLazyByteString)
34+ (toLazyByteString)
28−import qualified Data.ByteString.Char8 as BS
35+import qualified Data.ByteString.Char8 as BS
29−import qualified Data.ByteString.Lazy as BL
36+import qualified Data.ByteString.Lazy as BL
30import Data.CaseInsensitive
37import Data.CaseInsensitive
31import Data.Char
38import Data.Char
32−import Data.Foldable (toList)
39+import Data.Foldable
33−import Data.Functor.Alt (Alt (..))
41+import Data.Functor.Alt
34−import Data.IORef (modifyIORef, newIORef, readIORef)
42+ (Alt (..))
35−import Data.Proxy (Proxy (..))
44+ (Proxy (..))
36−import qualified Data.Sequence as Seq
45+import qualified Data.Sequence as Seq
37import Data.String.Conversions
46import Data.String.Conversions
38−import Data.Typeable (Typeable)
47+import Data.Typeable
39import Foreign.StablePtr
49import Foreign.StablePtr
40import GHC.Generics
50import GHC.Generics
41−import qualified GHCJS.Buffer as Buffer
51+import qualified GHCJS.Buffer as Buffer
42import GHCJS.Foreign.Callback
52import GHCJS.Foreign.Callback
43import GHCJS.Prim
53import GHCJS.Prim
44import GHCJS.Types
54import GHCJS.Types
45−import JavaScript.TypedArray.ArrayBuffer ( ArrayBuffer )
55+import JavaScript.TypedArray.ArrayBuffer
46import JavaScript.Web.Location
57import JavaScript.Web.Location
47−import Network.HTTP.Media (renderHeader)
58+import Network.HTTP.Media
48import Network.HTTP.Types
60import Network.HTTP.Types
49import Servant.Client.Core
61import Servant.Client.Core
62+import qualified Servant.Types.SourceT as S
51newtype JSXMLHttpRequest = JSXMLHttpRequest JSVal
64newtype JSXMLHttpRequest = JSXMLHttpRequest JSVal
@@ -110,9 +123,6 @@ instance RunClient ClientM where
110 runRequest = performRequest
123 runRequest = performRequest
111 throwServantError = throwError
124 throwServantError = throwError
113−instance ClientLike (ClientM a) (ClientM a) where
116runClientMOrigin :: ClientM a -> ClientEnv -> IO (Either ServantError a)
126runClientMOrigin :: ClientM a -> ClientEnv -> IO (Either ServantError a)
117runClientMOrigin cm env = runExceptT $ flip runReaderT env $ runClientM' cm
127runClientMOrigin cm env = runExceptT $ flip runReaderT env $ runClientM' cm
@@ -150,8 +160,9 @@ performRequest req = do
150 resp <- toResponse xhr
160 resp <- toResponse xhr
152 let status = statusCode (responseStatusCode resp)
162 let status = statusCode (responseStatusCode resp)
153− unless (status >= 200 && status < 300) $
163+ unless (status >= 200 && status < 300) $ do
164+ let f b = (burl, BL.toStrict $ toLazyByteString b)
154− throwError $ FailureResponse resp
165+ throwError $ FailureResponse (bimap (const ()) f req) resp
156 pure resp
167 pure resp
@@ -270,26 +281,17 @@ toBody request = case requestBody request of
271 go :: RequestBody -> IO ArrayBuffer
282 go :: RequestBody -> IO ArrayBuffer
272 go x = case x of
283 go x = case x of
273− RequestBodyLBS x -> return $ mBody $ BL.toStrict x
284+ RequestBodyLBS x -> return $ mBody $ BL.toStrict x
274− RequestBodyBS x -> return $ mBody x
285+ RequestBodyBS x -> return $ mBody x
275− RequestBodyBuilder _ x -> return $ mBody $ BL.toStrict $ toLazyByteString x
286+ RequestBodySource xs -> runExceptT (S.runSourceT xs) >>= \e -> case e of
276− RequestBodyStream _ x -> mBody <$> readBody x
287+ Left err -> fail err
277− RequestBodyStreamChunked x -> mBody <$> readBody x
288+ Right bss -> return $ mBody $ BL.toStrict $ mconcat bss
278− RequestBodyIO x -> x >>= go
280 mBody :: BS.ByteString -> ArrayBuffer
290 mBody :: BS.ByteString -> ArrayBuffer
281 mBody bs = js_bufferSlice offset len $ Buffer.getArrayBuffer buffer
291 mBody bs = js_bufferSlice offset len $ Buffer.getArrayBuffer buffer
283 (buffer, offset, len) = Buffer.fromByteString bs
293 (buffer, offset, len) = Buffer.fromByteString bs
285− readBody :: ((IO BS.ByteString -> IO ()) -> IO a) -> IO BS.ByteString
286− readBody writer = do
287− m <- newIORef mempty
288− _ <- writer (\bsAct -> do
290− modifyIORef m (<> bs))
293foreign import javascript unsafe "$3.slice($1, $1 + $2)"
295foreign import javascript unsafe "$3.slice($1, $1 + $2)"
294 js_bufferSlice :: Int -> Int -> ArrayBuffer -> ArrayBuffer
296 js_bufferSlice :: Int -> Int -> ArrayBuffer -> ArrayBuffer
@@ -301,7 +303,7 @@ toResponse :: JSXMLHttpRequest -> ClientM Response
301toResponse xhr = do
303toResponse xhr = do
302 status <- liftIO $ getStatus xhr
304 status <- liftIO $ getStatus xhr
303 case status of
305 case status of
304− 0 -> throwError $ ConnectionError "connection error"
306+ 0 -> throwError $ ConnectionError (SomeException (userError "connection error"))
305 _ -> liftIO $ do
307 _ -> liftIO $ do
306 statusText <- cs <$> getStatusText xhr
308 statusText <- cs <$> getStatusText xhr
307 headers <- parseHeaders <$> getAllResponseHeaders xhr
309 headers <- parseHeaders <$> getAllResponseHeaders xhr