Skip to content

Commit f8fea7c

Browse files
committed
Add HttpUtils
1 parent 9a214a8 commit f8fea7c

File tree

3 files changed

+78
-33
lines changed

3 files changed

+78
-33
lines changed

src/Internal/QueryM.purs

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import Control.Monad.Rec.Class (class MonadRec)
3030
import Control.Parallel (class Parallel, parallel, sequential)
3131
import Control.Plus (class Plus)
3232
import Ctl.Internal.Helpers (logWithLevel)
33+
import Ctl.Internal.QueryM.HttpUtils (handleAffjaxResponseGeneric)
3334
import Ctl.Internal.QueryM.Ogmios.QueryEnv (QueryRuntime)
3435
import Ctl.Internal.ServerConfig (ServerConfig)
3536
import Data.Bifunctor (lmap)
@@ -128,27 +129,17 @@ instance Parallel (QueryMT ParAff) (QueryMT Aff) where
128129
sequential :: QueryMT ParAff ~> QueryMT Aff
129130
sequential = wrap <<< sequential <<< unwrap
130131

131-
--------------------------------------------------------------------------------
132-
-- Affjax
133-
--------------------------------------------------------------------------------
134-
135-
-- Checks response status code and returns `ClientError` in case of failure,
136-
-- otherwise attempts to decode the result.
137-
--
138-
-- This function solves the problem described there:
139-
-- https://github.com/eviefp/purescript-affjax-errors
140132
handleAffjaxResponse
141133
:: forall (result :: Type)
142134
. DecodeAeson result
143135
=> Either Affjax.Error (Affjax.Response String)
144136
-> Either ClientError result
145-
handleAffjaxResponse (Left affjaxError) =
146-
Left (ClientHttpError affjaxError)
147-
handleAffjaxResponse
148-
(Right { status: Affjax.StatusCode.StatusCode statusCode, body })
149-
| statusCode < 200 || statusCode > 299 =
150-
Left $ ClientHttpResponseError (wrap statusCode) $ ServiceOtherError body
151-
| otherwise =
152-
body # lmap (ClientDecodeJsonError body)
153-
<<< (decodeAeson <=< parseJsonStringToAeson)
154-
137+
handleAffjaxResponse =
138+
handleAffjaxResponseGeneric
139+
ClientHttpError
140+
( \statusCode body -> ClientHttpResponseError (wrap statusCode)
141+
(ServiceOtherError body)
142+
)
143+
ClientDecodeJsonError
144+
(decodeAeson <=< parseJsonStringToAeson)
145+
pure

src/Internal/QueryM/HttpUtils.purs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
-- | This module defines utilities for working with HTTP requests
2+
module Ctl.Internal.QueryM.HttpUtils
3+
( handleAffjaxResponseGeneric
4+
) where
5+
6+
import Prelude
7+
8+
import Aeson (JsonDecodeError)
9+
import Affjax (Error, Response) as Affjax
10+
import Affjax.StatusCode as Affjax.StatusCode
11+
import Data.Bifunctor (lmap)
12+
import Data.Either (Either(Left, Right))
13+
14+
--------------------------------------------------------------------------------
15+
-- Affjax
16+
--------------------------------------------------------------------------------
17+
18+
-- Checks response status code and returns `ClientError` in case of failure,
19+
-- otherwise attempts to decode the result.
20+
--
21+
-- This function solves the problem described there:
22+
-- https://github.com/eviefp/purescript-affjax-errors
23+
24+
handleAffjaxResponseGeneric
25+
:: forall err intermediate result
26+
. (Affjax.Error -> err)
27+
-- ^ Convert an Affjax error into custom error
28+
-> (Int -> String -> err)
29+
-- ^ Convert a non-2xx status code into custom error
30+
-> (String -> JsonDecodeError -> err)
31+
-- ^ Wrap aeson-parse/decode errors
32+
-> (String -> Either JsonDecodeError intermediate)
33+
-- ^ Parse the response body
34+
-> (intermediate -> Either err result)
35+
-- ^ Function from `intermediate` to `result`
36+
-> Either Affjax.Error (Affjax.Response String)
37+
-- ^ Argument
38+
-> Either err result
39+
handleAffjaxResponseGeneric
40+
mkHttpError
41+
mkHttpResponseError
42+
mkDecodeError
43+
decodeAeson
44+
mkResult =
45+
case _ of
46+
Left affjaxError ->
47+
Left (mkHttpError affjaxError)
48+
Right { status: Affjax.StatusCode.StatusCode statusCode, body }
49+
| statusCode < 200 || statusCode > 299 ->
50+
Left (mkHttpResponseError statusCode body)
51+
| otherwise -> do
52+
intermediate <- lmap (mkDecodeError body) do
53+
decodeAeson body
54+
mkResult intermediate

src/Internal/QueryM/Ogmios.purs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import Affjax.ResponseFormat (string) as Affjax.ResponseFormat
2121
import Affjax.StatusCode (StatusCode(StatusCode))
2222
import Affjax.StatusCode as Affjax.StatusCode
2323
import Cardano.Provider.Error
24-
( ClientError(ClientHttpError, ClientHttpResponseError)
24+
( ClientError(ClientHttpError, ClientHttpResponseError, ClientDecodeJsonError)
2525
, ServiceError(ServiceOtherError)
2626
)
2727
import Cardano.Provider.TxEvaluation as Provider
@@ -33,13 +33,14 @@ import Control.Monad.Error.Class (class MonadThrow, throwError)
3333
import Control.Monad.Reader.Class (asks)
3434
import Ctl.Internal.Affjax (request) as Affjax
3535
import Ctl.Internal.QueryM (QueryM)
36+
import Ctl.Internal.QueryM.HttpUtils (handleAffjaxResponseGeneric)
3637
import Ctl.Internal.QueryM.Ogmios.Types
3738
( class DecodeOgmios
3839
, AdditionalUtxoSet
3940
, ChainTipQR(CtChainPoint, CtChainOrigin)
4041
, CurrentEpoch
4142
, DelegationsAndRewardsR
42-
, OgmiosDecodeError(ResultDecodingError, ClientErrorResponse)
43+
, OgmiosDecodeError(ClientErrorResponse)
4344
, OgmiosEraSummaries
4445
, OgmiosProtocolParameters
4546
, OgmiosSystemStart
@@ -137,7 +138,7 @@ ogmiosQueryNoParams
137138
. DecodeOgmios a
138139
=> String
139140
-> QueryM (Either OgmiosDecodeError a)
140-
ogmiosQueryNoParams method = do ogmiosQueryParams method {}
141+
ogmiosQueryNoParams = flip ogmiosQueryParams {}
141142

142143
ogmiosQueryParams
143144
:: forall a p
@@ -201,17 +202,16 @@ handleAffjaxOgmiosResponse
201202
. DecodeOgmios result
202203
=> Either Affjax.Error (Affjax.Response String)
203204
-> Either OgmiosDecodeError result
204-
handleAffjaxOgmiosResponse (Left affjaxError) =
205-
Left (ClientErrorResponse $ ClientHttpError affjaxError)
206-
handleAffjaxOgmiosResponse
207-
(Right { status: Affjax.StatusCode.StatusCode statusCode, body })
208-
| statusCode < 200 || statusCode > 299 =
209-
Left $ ClientErrorResponse $ ClientHttpResponseError (wrap statusCode) $
210-
ServiceOtherError body
211-
| otherwise = do
212-
aeson <- lmap ResultDecodingError
213-
$ parseJsonStringToAeson body
214-
decodeOgmios aeson
205+
handleAffjaxOgmiosResponse =
206+
handleAffjaxResponseGeneric
207+
(ClientErrorResponse <<< ClientHttpError)
208+
( \statusCode body -> ClientErrorResponse $ ClientHttpResponseError
209+
(wrap statusCode)
210+
(ServiceOtherError body)
211+
)
212+
(\body -> ClientErrorResponse <<< ClientDecodeJsonError body)
213+
parseJsonStringToAeson
214+
decodeOgmios
215215

216216
ogmiosErrorHandler
217217
:: forall a m

0 commit comments

Comments
 (0)