git.iko.soy/rowtype-yoga/purescript-fetch
on main help sign in
83 lines 3.3 kB history raw
1module Fetch
2 ( fetch
3 , module Data.HTTP.Method
4 , module JS.Fetch.RequestCache
5 , module JS.Fetch.RequestCredentials
6 , module JS.Fetch.RequestMode
7 , module JS.Fetch.Referrer
8 , module JS.Fetch.Integrity
9 , module Fetch.Internal.Request
10 , module Fetch.Internal.RequestBody
11 , module Fetch.Internal.Response
12 , module Fetch.Internal.Headers
13 ) where
15import Prelude
17import Data.Either (Either(Left, Right))
18import Data.HTTP.Method (Method(..))
19import Effect.Aff (Aff, effectCanceler, makeAff)
20import Effect.Class (liftEffect)
21import Fetch.Internal.Headers (contains, lookup, toHeaders)
22import Fetch.Internal.Request (class ToCoreRequestOptions, class ToCoreRequestOptionsConverter, class ToCoreRequestOptionsHelper, HighlevelRequestOptions, convertHelper, convertImpl, new)
23import Fetch.Internal.RequestBody (class ToRequestBody, toRequestBody)
24import Fetch.Internal.Response (Response, ResponseR, arrayBuffer, blob, body, json, text)
25import JS.Fetch.AbortController (AbortController)
26import JS.Fetch.Integrity (Integrity(..))
27import JS.Fetch.Referrer (Referrer(..))
28import JS.Fetch.RequestCache (RequestCache(..))
29import JS.Fetch.RequestCredentials (RequestCredentials(Include, Omit))
30import JS.Fetch.RequestMode (RequestMode(Cors, Navigate, NoCors))
31import Prim.Row (class Union)
32import JS.Fetch.AbortController (abort, new, signal) as AbortController
33import JS.Fetch as Core
34import JS.Fetch.Request as CoreRequest
35import Promise (Promise, resolve, thenOrCatch) as Promise
36import Promise.Aff as Promise.Aff
37import Fetch.Internal.Request as Request
38import Fetch.Internal.Response as Response
40-- | Implementation of `fetch`, see https://developer.mozilla.org/en-US/docs/Web/API/fetch
41-- |
42-- | Usage:
43-- | ```purescript
44-- | do
45-- | let requestUrl = "https://httpbin.org/get"
46-- | { status, text } <- fetch requestUrl { headers: { "Accept": "application/json" }}
47-- | responseBody <- text
48-- | ```
49-- | A more complex example doing a Post request:
50-- | ```purescript
51-- | do
52-- | { status, json } <- fetch "https://httpbin.org/post"
53-- | { method: POST
54-- | , mode: RequestMode.Cors
55-- | , body: """{"hello":"world"}"""
56-- | , headers: { "Content-Type": "application/json" }
57-- | , referrer: ReferrerUrl "https://httpbin.org"
58-- | }
59-- | foreignJsonValue <- json
60-- | ```
61fetch
62 :: forall input output @thruIn thruOut headers body
63 . Union input thruIn (HighlevelRequestOptions headers body)
64 => Union output thruOut CoreRequest.UnsafeRequestOptions
65 => ToCoreRequestOptions input output
66 => String
67 -> { | input }
68 -> Aff Response
69fetch url r = do
70 request <- liftEffect $ new url $ Request.convert r
71 abortController <- AbortController.new # liftEffect
72 let signal = AbortController.signal abortController
73 cResponse <- toAbortableAff abortController =<< liftEffect (Core.fetchWithOptions request { signal })
74 pure $ Response.convert cResponse
76toAbortableAff :: forall a. AbortController -> Promise.Promise a -> Aff a
77toAbortableAff abortController p = makeAff \cb -> do
78 void $ Promise.thenOrCatch
79 (\a -> Promise.resolve <$> cb (Right a))
80 (\e -> Promise.resolve <$> cb (Left (Promise.Aff.coerce e)))
81 p
82 pure $ effectCanceler (AbortController.abort abortController)