@@ -19,26 +19,28 @@ module Network.HTTP.Affjax
19
19
20
20
import Prelude hiding (max )
21
21
22
- import Control.Monad.Aff (Aff , makeAff , makeAff' , Canceler (..), attempt , later' , forkAff , cancel )
22
+ import Control.Monad.Aff (Aff , makeAff , makeAff' , Canceler (..), attempt , delay , forkAff , cancel )
23
23
import Control.Monad.Aff.AVar (AVAR , makeVar , takeVar , putVar )
24
- import Control.Monad.Eff (Eff )
24
+ import Control.Monad.Eff (kind Effect , Eff )
25
25
import Control.Monad.Eff.Class (liftEff )
26
26
import Control.Monad.Eff.Exception (Error , error )
27
27
import Control.Monad.Eff.Ref (REF , newRef , readRef , writeRef )
28
28
import Control.Monad.Except (runExcept , throwError )
29
29
30
+ import Data.Argonaut.Parser (jsonParser )
30
31
import Data.Array as Arr
31
32
import Data.Either (Either (..), either )
32
33
import Data.Foldable (any )
33
- import Data.Foreign (Foreign , F , parseJSON , readString )
34
+ import Data.Foreign (F , Foreign , ForeignError (JSONError), fail , readString , toForeign )
34
35
import Data.Function (on )
35
36
import Data.Function.Uncurried (Fn5 , runFn5 , Fn4 , runFn4 )
36
37
import Data.HTTP.Method (Method (..), CustomMethod )
37
38
import Data.HTTP.Method as Method
38
- import Data.Int (toNumber , round )
39
+ import Data.Int (toNumber )
39
40
import Data.Maybe (Maybe (..))
40
41
import Data.MediaType (MediaType )
41
42
import Data.Nullable (Nullable , toNullable )
43
+ import Data.Time.Duration (Milliseconds (..))
42
44
import Data.Tuple (Tuple (..), fst , snd )
43
45
44
46
import Math (max , pow )
@@ -52,7 +54,7 @@ import Network.HTTP.ResponseHeader (ResponseHeader, responseHeader)
52
54
import Network.HTTP.StatusCode (StatusCode (..))
53
55
54
56
-- | The effect type for AJAX requests made with Affjax.
55
- foreign import data AJAX :: !
57
+ foreign import data AJAX :: Effect
56
58
57
59
-- | The type for Affjax requests.
58
60
type Affjax e a = Aff (ajax :: AJAX | e ) (AffjaxResponse a )
@@ -89,81 +91,81 @@ type AffjaxResponse a =
89
91
type URL = String
90
92
91
93
-- | Makes an `Affjax` request.
92
- affjax :: forall e a b . ( Requestable a , Respondable b ) => AffjaxRequest a -> Affjax e b
94
+ affjax :: forall e a b . Requestable a => Respondable b => AffjaxRequest a -> Affjax e b
93
95
affjax = makeAff' <<< affjax'
94
96
95
97
-- | Makes a `GET` request to the specified URL.
96
- get :: forall e a . ( Respondable a ) => URL -> Affjax e a
98
+ get :: forall e a . Respondable a => URL -> Affjax e a
97
99
get u = affjax $ defaultRequest { url = u }
98
100
99
101
-- | Makes a `POST` request to the specified URL, sending data.
100
- post :: forall e a b . ( Requestable a , Respondable b ) => URL -> a -> Affjax e b
102
+ post :: forall e a b . Requestable a => Respondable b => URL -> a -> Affjax e b
101
103
post u c = affjax $ defaultRequest { method = Left POST , url = u, content = Just c }
102
104
103
105
-- | Makes a `POST` request to the specified URL with the option to send data.
104
- post' :: forall e a b . ( Requestable a , Respondable b ) => URL -> Maybe a -> Affjax e b
106
+ post' :: forall e a b . Requestable a => Respondable b => URL -> Maybe a -> Affjax e b
105
107
post' u c = affjax $ defaultRequest { method = Left POST , url = u, content = c }
106
108
107
109
-- | Makes a `POST` request to the specified URL, sending data and ignoring the
108
110
-- | response.
109
- post_ :: forall e a . ( Requestable a ) => URL -> a -> Affjax e Unit
111
+ post_ :: forall e a . Requestable a => URL -> a -> Affjax e Unit
110
112
post_ = post
111
113
112
114
-- | Makes a `POST` request to the specified URL with the option to send data,
113
115
-- | and ignores the response.
114
- post_' :: forall e a . ( Requestable a ) => URL -> Maybe a -> Affjax e Unit
116
+ post_' :: forall e a . Requestable a => URL -> Maybe a -> Affjax e Unit
115
117
post_' = post'
116
118
117
119
-- | Makes a `PUT` request to the specified URL, sending data.
118
- put :: forall e a b . ( Requestable a , Respondable b ) => URL -> a -> Affjax e b
120
+ put :: forall e a b . Requestable a => Respondable b => URL -> a -> Affjax e b
119
121
put u c = affjax $ defaultRequest { method = Left PUT , url = u, content = Just c }
120
122
121
123
-- | Makes a `PUT` request to the specified URL with the option to send data.
122
- put' :: forall e a b . ( Requestable a , Respondable b ) => URL -> Maybe a -> Affjax e b
124
+ put' :: forall e a b . Requestable a => Respondable b => URL -> Maybe a -> Affjax e b
123
125
put' u c = affjax $ defaultRequest { method = Left PUT , url = u, content = c }
124
126
125
127
-- | Makes a `PUT` request to the specified URL, sending data and ignoring the
126
128
-- | response.
127
- put_ :: forall e a . ( Requestable a ) => URL -> a -> Affjax e Unit
129
+ put_ :: forall e a . Requestable a => URL -> a -> Affjax e Unit
128
130
put_ = put
129
131
130
132
-- | Makes a `PUT` request to the specified URL with the option to send data,
131
133
-- | and ignores the response.
132
- put_' :: forall e a . ( Requestable a ) => URL -> Maybe a -> Affjax e Unit
134
+ put_' :: forall e a . Requestable a => URL -> Maybe a -> Affjax e Unit
133
135
put_' = put'
134
136
135
137
-- | Makes a `DELETE` request to the specified URL.
136
- delete :: forall e a . ( Respondable a ) => URL -> Affjax e a
138
+ delete :: forall e a . Respondable a => URL -> Affjax e a
137
139
delete u = affjax $ defaultRequest { method = Left DELETE , url = u }
138
140
139
141
-- | Makes a `DELETE` request to the specified URL and ignores the response.
140
142
delete_ :: forall e . URL -> Affjax e Unit
141
143
delete_ = delete
142
144
143
145
-- | Makes a `PATCH` request to the specified URL, sending data.
144
- patch :: forall e a b . ( Requestable a , Respondable b ) => URL -> a -> Affjax e b
146
+ patch :: forall e a b . Requestable a => Respondable b => URL -> a -> Affjax e b
145
147
patch u c = affjax $ defaultRequest { method = Left PATCH , url = u, content = Just c }
146
148
147
149
-- | Makes a `PATCH` request to the specified URL with the option to send data.
148
- patch' :: forall e a b . ( Requestable a , Respondable b ) => URL -> Maybe a -> Affjax e b
150
+ patch' :: forall e a b . Requestable a => Respondable b => URL -> Maybe a -> Affjax e b
149
151
patch' u c = affjax $ defaultRequest { method = Left PATCH , url = u, content = c }
150
152
151
153
-- | Makes a `PATCH` request to the specified URL, sending data and ignoring the
152
154
-- | response.
153
- patch_ :: forall e a . ( Requestable a ) => URL -> a -> Affjax e Unit
155
+ patch_ :: forall e a . Requestable a => URL -> a -> Affjax e Unit
154
156
patch_ = patch
155
157
156
158
-- | Makes a `PATCH` request to the specified URL with the option to send data,
157
159
-- | and ignores the response.
158
- patch_' :: forall e a . ( Requestable a ) => URL -> Maybe a -> Affjax e Unit
160
+ patch_' :: forall e a . Requestable a => URL -> Maybe a -> Affjax e Unit
159
161
patch_' = patch'
160
162
161
163
-- | A sequence of retry delays, in milliseconds.
162
- type RetryDelayCurve = Int -> Int
164
+ type RetryDelayCurve = Int -> Milliseconds
163
165
164
166
-- | Expresses a policy for retrying Affjax requests with backoff.
165
167
type RetryPolicy =
166
- { timeout :: Maybe Int -- ^ the timeout in milliseconds, optional
168
+ { timeout :: Maybe Milliseconds -- ^ the timeout in milliseconds, optional
167
169
, delayCurve :: RetryDelayCurve
168
170
, shouldRetryWithStatusCode :: StatusCode -> Boolean -- ^ whether a non-200 status code should trigger a retry
169
171
}
@@ -172,7 +174,7 @@ type RetryPolicy =
172
174
defaultRetryPolicy :: RetryPolicy
173
175
defaultRetryPolicy =
174
176
{ timeout : Nothing
175
- , delayCurve : \n -> round $ max (30.0 * 1000.0 ) $ 100.0 * (pow 2.0 $ toNumber (n - 1 ))
177
+ , delayCurve : \n -> Milliseconds $ max (30.0 * 1000.0 ) $ 100.0 * (pow 2.0 $ toNumber (n - 1 ))
176
178
, shouldRetryWithStatusCode : const false
177
179
}
178
180
@@ -182,7 +184,7 @@ type RetryState e a = Either (Either e a) a
182
184
-- | Retry a request using a `RetryPolicy`. After the timeout, the last received response is returned; if it was not possible to communicate with the server due to an error, then this is bubbled up.
183
185
retry
184
186
:: forall e a b
185
- . ( Requestable a )
187
+ . Requestable a
186
188
=> RetryPolicy
187
189
-> (AffjaxRequest a -> Affjax (avar :: AVAR , ref :: REF | e ) b )
188
190
-> (AffjaxRequest a -> Affjax (avar :: AVAR , ref :: REF | e ) b )
@@ -196,7 +198,8 @@ retry policy run req = do
196
198
respVar <- makeVar
197
199
loopHandle <- forkAff $ loop 1 >>= putVar respVar <<< Just
198
200
timeoutHandle <-
199
- forkAff <<< later' timeout $ do
201
+ forkAff $ do
202
+ delay timeout
200
203
putVar respVar Nothing
201
204
loopHandle `cancel` error " Cancel"
202
205
result <- takeVar respVar
@@ -226,13 +229,15 @@ retry policy run req = do
226
229
case result of
227
230
Left err -> do
228
231
liftEff $ writeRef failureRef $ Just err
229
- later' (policy.delayCurve n) $ go failureRef (n + 1 )
232
+ delay (policy.delayCurve n)
233
+ go failureRef (n + 1 )
230
234
Right resp -> pure resp
231
235
232
236
-- | Run a request directly without using `Aff`.
233
237
affjax'
234
238
:: forall e a b
235
- . (Requestable a , Respondable b )
239
+ . Requestable a
240
+ => Respondable b
236
241
=> AffjaxRequest a
237
242
-> (Error -> Eff (ajax :: AJAX | e ) Unit )
238
243
-> (AffjaxResponse b -> Eff (ajax :: AJAX | e ) Unit )
@@ -277,6 +282,9 @@ affjax' req eb cb =
277
282
Left err -> eb $ error (show err )
278
283
Right res' -> cb res'
279
284
285
+ parseJSON :: String -> F Foreign
286
+ parseJSON = either (fail <<< JSONError ) (pure <<< toForeign ) <<< jsonParser
287
+
280
288
fromResponse' :: ResponseContent -> F b
281
289
fromResponse' = case snd responseSettings of
282
290
JSONResponse -> fromResponse <= < parseJSON <= < readString
0 commit comments