1
1
import gleam/dynamic . { type Dynamic }
2
- import gleam/fetch/fetch_options . { type FetchOptions }
3
2
import gleam/fetch/form_data . { type FormData }
4
3
import gleam/http/request . { type Request }
5
4
import gleam/http/response . { type Response }
@@ -46,6 +45,13 @@ pub fn raw_send(
46
45
request : FetchRequest ,
47
46
) -> Promise ( Result ( FetchResponse , FetchError ) )
48
47
48
+ /// Bridge for Request with FetchOptions between Gleam and JavaScript.
49
+ @ external ( javascript , "../gleam_fetch_ffi.mjs" , "raw_send" )
50
+ fn raw_send_converted_options (
51
+ request : FetchRequest ,
52
+ options : FetchOptionsNative ,
53
+ ) -> Promise ( Result ( FetchResponse , FetchError ) )
54
+
49
55
/// Call directly `fetch` with a `Request` and `FetchOptions`,
50
56
/// then convert the result back to Gleam.
51
57
/// Let you get back a `FetchResponse` instead of the Gleam
@@ -56,13 +62,24 @@ pub fn raw_send(
56
62
/// |> request.set_host("example.com")
57
63
/// |> request.set_path("/example")
58
64
/// |> fetch.to_fetch_request
59
- /// |> fetch.raw_send_with (fetch_options.new())
65
+ /// |> fetch.raw_send_options (fetch_options.new())
60
66
/// ```
61
- @ external ( javascript , "../gleam_fetch_ffi.mjs" , "raw_send" )
62
- pub fn raw_send_with (
67
+ pub fn raw_send_options (
63
68
request : FetchRequest ,
64
69
options : FetchOptions ,
65
- ) -> Promise ( Result ( FetchResponse , FetchError ) )
70
+ ) -> Promise ( Result ( FetchResponse , FetchError ) ) {
71
+ raw_send_converted_options (
72
+ request ,
73
+ FetchOptionsNative (
74
+ cache : cache_to_string ( options . cache ) ,
75
+ credentials : credentials_to_string ( options . credentials ) ,
76
+ keepalive : options . keepalive ,
77
+ mode : cors_to_string ( options . mode ) ,
78
+ priority : priority_to_string ( options . priority ) ,
79
+ redirect : redirect_to_string ( options . redirect ) ,
80
+ ) ,
81
+ )
82
+ }
66
83
67
84
/// Call `fetch` with a Gleam `Request(String)`, and convert the result back
68
85
/// to Gleam. Use it to send strings or JSON stringified.
@@ -95,7 +112,7 @@ pub fn send(
95
112
/// Use it to send strings or JSON stringified.
96
113
///
97
114
/// If you're looking for something more low-level, take a look at
98
- /// [`raw_send_with `](#raw_send_with ).
115
+ /// [`raw_send_options `](#raw_send_options ).
99
116
///
100
117
/// ```gleam
101
118
/// let my_data = json.object([#("field", "value")])
@@ -104,15 +121,15 @@ pub fn send(
104
121
/// |> request.set_path("/example")
105
122
/// |> request.set_body(json.to_string(my_data))
106
123
/// |> request.set_header("content-type", "application/json")
107
- /// |> fetch.send_with (fetch_options.new())
124
+ /// |> fetch.send_options (fetch_options.new())
108
125
/// ```
109
- pub fn send_with (
126
+ pub fn send_options (
110
127
request : Request ( String ) ,
111
128
options : FetchOptions ,
112
129
) -> Promise ( Result ( Response ( FetchBody ) , FetchError ) ) {
113
130
request
114
131
|> to_fetch_request
115
- |> raw_send_with ( options )
132
+ |> raw_send_options ( options )
116
133
|> promise . try_await ( fn ( resp ) {
117
134
promise . resolve ( Ok ( from_fetch_response ( resp ) ) )
118
135
} )
@@ -152,7 +169,7 @@ pub fn send_form_data(
152
169
/// decoded as-is on servers.
153
170
///
154
171
/// If you're looking for something more low-level, take a look at
155
- /// [`raw_send_with `](#raw_send_with ).
172
+ /// [`raw_send_options `](#raw_send_options ).
156
173
///
157
174
/// ```gleam
158
175
/// request.new()
@@ -162,15 +179,15 @@ pub fn send_form_data(
162
179
/// form_data.new()
163
180
/// |> form_data.append("key", "value")
164
181
/// })
165
- /// |> fetch.send_form_data_with (fetch_options.new())
182
+ /// |> fetch.send_form_data_options (fetch_options.new())
166
183
/// ```
167
- pub fn send_form_data_with (
184
+ pub fn send_form_data_options (
168
185
request : Request ( FormData ) ,
169
186
options : FetchOptions ,
170
187
) -> Promise ( Result ( Response ( FetchBody ) , FetchError ) ) {
171
188
request
172
189
|> form_data_to_fetch_request
173
- |> raw_send_with ( options )
190
+ |> raw_send_options ( options )
174
191
|> promise . try_await ( fn ( resp ) {
175
192
promise . resolve ( Ok ( from_fetch_response ( resp ) ) )
176
193
} )
@@ -207,23 +224,23 @@ pub fn send_bits(
207
224
/// and you probably want a proper content-type added.
208
225
///
209
226
/// If you're looking for something more low-level, take a look at
210
- /// [`raw_send_with `](#raw_send_with ).
227
+ /// [`raw_send_options `](#raw_send_options ).
211
228
///
212
229
/// ```gleam
213
230
/// request.new()
214
231
/// |> request.set_host("example.com")
215
232
/// |> request.set_path("/example")
216
233
/// |> request.set_body(<<"data">>)
217
234
/// |> request.set_header("content-type", "application/octet-stream")
218
- /// |> fetch.send_bits_with (fetch_options.new())
235
+ /// |> fetch.send_bits_options (fetch_options.new())
219
236
/// ```
220
- pub fn send_bits_with (
237
+ pub fn send_bits_options (
221
238
request : Request ( BitArray ) ,
222
239
options : FetchOptions ,
223
240
) -> Promise ( Result ( Response ( FetchBody ) , FetchError ) ) {
224
241
request
225
242
|> bitarray_request_to_fetch_request
226
- |> raw_send_with ( options )
243
+ |> raw_send_options ( options )
227
244
|> promise . try_await ( fn ( resp ) {
228
245
promise . resolve ( Ok ( from_fetch_response ( resp ) ) )
229
246
} )
@@ -363,3 +380,250 @@ pub fn read_text_body(
363
380
pub fn read_json_body (
364
381
a : Response ( FetchBody ) ,
365
382
) -> Promise ( Result ( Response ( Dynamic ) , FetchError ) )
383
+
384
+ /// Gleam equivalent of JavaScript
385
+ /// [`RequestInit`](https://developer.mozilla.org/docs/Web/API/RequestInit).
386
+ ///
387
+ /// The Node target supports only the `redirect` and `priority` options.
388
+ pub opaque type FetchOptions {
389
+ Builder (
390
+ cache : Cache ,
391
+ credentials : Credentials ,
392
+ keepalive : Bool ,
393
+ mode : Cors ,
394
+ priority : Priority ,
395
+ redirect : Redirect ,
396
+ )
397
+ }
398
+
399
+ // Converted internal FetchOptions to be send via JavaScript.
400
+ type FetchOptionsNative {
401
+ FetchOptionsNative (
402
+ cache : String ,
403
+ credentials : String ,
404
+ keepalive : Bool ,
405
+ mode : String ,
406
+ priority : String ,
407
+ redirect : String ,
408
+ )
409
+ }
410
+
411
+ /// Cache options, for details see
412
+ /// [`cache`](https://developer.mozilla.org/docs/Web/API/RequestInit#cache).
413
+ ///
414
+ /// Change how responses are stored and retrieved from cache.
415
+ pub type Cache {
416
+ /// Default cache behaviour.
417
+ ///
418
+ /// Fresh record will be returned from the cache.
419
+ /// If the record in cache is stale and server responds with not
420
+ /// changed, then the value from cache is used. Otherwise makes normal
421
+ /// request and updates the cache.
422
+ Default
423
+ /// Response is not fetched from the cache and not stored in the cache.
424
+ NoStore
425
+ /// Response is not fetched from the cache but gets stored.
426
+ Reload
427
+ /// If the record in cache is fresh or stale and server responds with not
428
+ /// changed, then the value from cache is used. Otherwise makes normal
429
+ /// request and updates the cache.
430
+ NoCache
431
+ /// If record is in cache, it is always used. Otherwise makes normal
432
+ /// request.
433
+ ForceCache
434
+ }
435
+
436
+ fn cache_to_string ( cache : Cache ) -> String {
437
+ case cache {
438
+ Default -> "default"
439
+ NoStore -> "no-store"
440
+ Reload -> "reload"
441
+ NoCache -> "no-cache"
442
+ ForceCache -> "force-cache"
443
+ }
444
+ }
445
+
446
+ /// Credentials options, for details see
447
+ /// [`credentials`](https://developer.mozilla.org/docs/Web/API/RequestInit#credentials).
448
+ ///
449
+ /// Control whether browser sends credentials with the request and whether
450
+ /// Set-Cookie response headers are respected.
451
+ pub type Credentials {
452
+ /// Never send credentials or include credentials in the response.
453
+ CredentialsOmit
454
+ /// Only send and include credentials for same-origin requests.
455
+ CredentialsSameOrigin
456
+ /// Always include credentials.
457
+ CredentialsInclude
458
+ }
459
+
460
+ fn credentials_to_string ( credentials : Credentials ) -> String {
461
+ case credentials {
462
+ CredentialsOmit -> "omit"
463
+ CredentialsSameOrigin -> "same-origin"
464
+ CredentialsInclude -> "include"
465
+ }
466
+ }
467
+
468
+ /// CORS options, for details see
469
+ /// [`mode`](https://developer.mozilla.org/docs/Web/API/RequestInit#mode).
470
+ ///
471
+ /// Set cross-origin behaviour of a request.
472
+ pub type Cors {
473
+ /// Disallows cross-origin requests.
474
+ SameOrigin
475
+ /// Defaults to
476
+ /// [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS)
477
+ /// mechanism.
478
+ Cors
479
+ /// Disables CORS for cross-origin requests.
480
+ NoCors
481
+ /// Used only by HTML navigation.
482
+ Navigate
483
+ }
484
+
485
+ fn cors_to_string ( cors : Cors ) -> String {
486
+ case cors {
487
+ SameOrigin -> "same-origin"
488
+ Cors -> "cors"
489
+ NoCors -> "no-cors"
490
+ Navigate -> "navigate"
491
+ }
492
+ }
493
+
494
+ /// Priority options, for details see
495
+ /// [`priority`](https://developer.mozilla.org/docs/Web/API/RequestInit#priority).
496
+ ///
497
+ /// Increase priority of a request relative to other requests.
498
+ pub type Priority {
499
+ /// Higher priority.
500
+ High
501
+ /// Lower priority.
502
+ Low
503
+ /// No preference of priority.
504
+ Auto
505
+ }
506
+
507
+ fn priority_to_string ( priority : Priority ) -> String {
508
+ case priority {
509
+ High -> "high"
510
+ Low -> "low"
511
+ Auto -> "auto"
512
+ }
513
+ }
514
+
515
+ /// Redirect options, for details see
516
+ /// [`redirect`](https://developer.mozilla.org/docs/Web/API/RequestInit#redirect).
517
+ ///
518
+ /// Change the redirect behaviour of a request.
519
+ pub type Redirect {
520
+ /// Automatically redirects request.
521
+ Follow
522
+ /// Errors out on redirect.
523
+ Error
524
+ /// Expects user to handle redirects manually.
525
+ Manual
526
+ }
527
+
528
+ fn redirect_to_string ( redirect : Redirect ) -> String {
529
+ case redirect {
530
+ Follow -> "follow"
531
+ Error -> "error"
532
+ Manual -> "manual"
533
+ }
534
+ }
535
+
536
+ /// Creates new `FetchOptions` object with default values.
537
+ ///
538
+ /// Useful if more precise control over fetch is required, such as using
539
+ /// signals, cache options and so on.
540
+ ///
541
+ /// ```gleam
542
+ /// let options = fetch_options.new()
543
+ /// |> fetch_options.cache(fetch_options.NoStore)
544
+ /// ```
545
+ pub fn fetch_options ( ) -> FetchOptions {
546
+ Builder (
547
+ cache : Default ,
548
+ credentials : CredentialsSameOrigin ,
549
+ keepalive : False ,
550
+ mode : Cors ,
551
+ priority : Auto ,
552
+ redirect : Follow ,
553
+ )
554
+ }
555
+
556
+ /// Set the
557
+ /// [`cache`](https://developer.mozilla.org/docs/Web/API/RequestInit#cache)
558
+ /// option of `FetchOptions`.
559
+ ///
560
+ /// ```gleam
561
+ /// let options = fetch_options.new()
562
+ /// |> fetch_options.cache(fetch_options.NoStore)
563
+ /// ```
564
+ pub fn cache ( fetch_options : FetchOptions , which : Cache ) -> FetchOptions {
565
+ Builder ( .. fetch_options , cache : which )
566
+ }
567
+
568
+ /// Set the
569
+ /// [`credentials`](https://developer.mozilla.org/docs/Web/API/RequestInit#credentials)
570
+ /// option of `FetchOptions`.
571
+ ///
572
+ /// ```gleam
573
+ /// let options = fetch_options.new()
574
+ /// |> fetch_options.credentials(fetch_options.CredentialsOmit)
575
+ /// ```
576
+ pub fn credentials (
577
+ fetch_options : FetchOptions ,
578
+ which : Credentials ,
579
+ ) -> FetchOptions {
580
+ Builder ( .. fetch_options , credentials : which )
581
+ }
582
+
583
+ /// Set the
584
+ /// [`keepalive`](https://developer.mozilla.org/docs/Web/API/RequestInit#keepalive)
585
+ /// option of `FetchOptions`.
586
+ ///
587
+ /// ```gleam
588
+ /// let options = fetch_options.new()
589
+ /// |> fetch_options.keepalive(True)
590
+ /// ```
591
+ pub fn keepalive ( fetch_options : FetchOptions , keepalive : Bool ) -> FetchOptions {
592
+ Builder ( .. fetch_options , keepalive : keepalive )
593
+ }
594
+
595
+ /// Set the
596
+ /// [`cors`](https://developer.mozilla.org/docs/Web/API/RequestInit#mode)
597
+ /// option of `FetchOptions`.
598
+ ///
599
+ /// ```gleam
600
+ /// let options = fetch_options.new()
601
+ /// |> fetch_options.cors(fetch_options.SameOrigin)
602
+ /// ```
603
+ pub fn cors ( fetch_options : FetchOptions , which : Cors ) -> FetchOptions {
604
+ Builder ( .. fetch_options , mode : which )
605
+ }
606
+
607
+ /// Set the
608
+ /// [`priority`](https://developer.mozilla.org/docs/Web/API/RequestInit#priority)
609
+ /// option of `FetchOptions`.
610
+ ///
611
+ /// ```gleam
612
+ /// let options = fetch_options.new()
613
+ /// |> fetch_options.cors(fetch_options.High)
614
+ /// ```
615
+ pub fn priority ( fetch_options : FetchOptions , which : Priority ) -> FetchOptions {
616
+ Builder ( .. fetch_options , priority : which )
617
+ }
618
+
619
+ /// Set the
620
+ /// [`redirect`](https://developer.mozilla.org/docs/Web/API/RequestInit#redirect)
621
+ /// option of `FetchOptions`.
622
+ ///
623
+ /// ```gleam
624
+ /// let options = fetch_options.new()
625
+ /// |> fetch_options.redirect(fetch_options.Follow)
626
+ /// ```
627
+ pub fn redirect ( fetch_options : FetchOptions , which : Redirect ) -> FetchOptions {
628
+ Builder ( .. fetch_options , redirect : which )
629
+ }
0 commit comments