50
50
51
51
use rune:: alloc:: fmt:: TryWrite ;
52
52
use rune:: runtime:: { Bytes , Formatter , Ref , VmResult } ;
53
- use rune:: { Any , ContextError , Module , Value } ;
53
+ use rune:: { docstring , Any , ContextError , Module , Value } ;
54
54
55
55
/// A simple HTTP module for Rune.
56
56
///
@@ -69,26 +69,56 @@ pub fn module(_stdio: bool) -> Result<Module, ContextError> {
69
69
module. ty :: < Response > ( ) ?;
70
70
module. ty :: < RequestBuilder > ( ) ?;
71
71
module. ty :: < StatusCode > ( ) ?;
72
+ module. ty :: < Version > ( ) ?;
72
73
module. ty :: < Error > ( ) ?;
73
74
74
- module. function_meta ( Client :: new) ?;
75
75
module. function_meta ( get) ?;
76
76
77
+ module. function_meta ( Client :: new) ?;
77
78
module. function_meta ( Client :: get) ?;
78
79
module. function_meta ( Client :: post) ?;
80
+ module. function_meta ( Client :: put) ?;
81
+ module. function_meta ( Client :: delete) ?;
82
+ module. function_meta ( Client :: head) ?;
79
83
80
84
module. function_meta ( Response :: text) ?;
81
85
module. function_meta ( Response :: json) ?;
82
86
module. function_meta ( Response :: bytes) ?;
83
87
module. function_meta ( Response :: status) ?;
88
+ module. function_meta ( Response :: version) ?;
89
+ module. function_meta ( Response :: content_length) ?;
84
90
85
91
module. function_meta ( RequestBuilder :: send) ?;
86
92
module. function_meta ( RequestBuilder :: header) ?;
87
- module. function_meta ( RequestBuilder :: body_bytes) ?;
93
+ module. function_meta ( RequestBuilder :: basic_auth) ?;
94
+ module. function_meta ( RequestBuilder :: bearer_auth) ?;
88
95
module. function_meta ( RequestBuilder :: fetch_mode_no_cors) ?;
96
+ module. function_meta ( RequestBuilder :: body_bytes) ?;
89
97
90
- module. function_meta ( Error :: string_display) ?;
91
98
module. function_meta ( StatusCode :: string_display) ?;
99
+ module. function_meta ( StatusCode :: as_u16) ?;
100
+ module. function_meta ( StatusCode :: as_str) ?;
101
+ module. function_meta ( StatusCode :: canonical_reason) ?;
102
+ module. function_meta ( StatusCode :: is_informational) ?;
103
+ module. function_meta ( StatusCode :: is_success) ?;
104
+ module. function_meta ( StatusCode :: is_redirection) ?;
105
+ module. function_meta ( StatusCode :: is_client_error) ?;
106
+ module. function_meta ( StatusCode :: is_server_error) ?;
107
+
108
+ module. implement_trait :: < StatusCode > ( rune:: item!( :: std:: cmp:: PartialEq ) ) ?;
109
+ module. implement_trait :: < StatusCode > ( rune:: item!( :: std:: cmp:: Eq ) ) ?;
110
+ module. implement_trait :: < StatusCode > ( rune:: item!( :: std:: cmp:: PartialOrd ) ) ?;
111
+ module. implement_trait :: < StatusCode > ( rune:: item!( :: std:: cmp:: Ord ) ) ?;
112
+
113
+ module. function_meta ( Version :: string_display) ?;
114
+
115
+ module. implement_trait :: < Version > ( rune:: item!( :: std:: cmp:: PartialEq ) ) ?;
116
+ module. implement_trait :: < Version > ( rune:: item!( :: std:: cmp:: Eq ) ) ?;
117
+ module. implement_trait :: < Version > ( rune:: item!( :: std:: cmp:: PartialOrd ) ) ?;
118
+ module. implement_trait :: < Version > ( rune:: item!( :: std:: cmp:: Ord ) ) ?;
119
+
120
+ module. function_meta ( Error :: string_display) ?;
121
+
92
122
Ok ( module)
93
123
}
94
124
@@ -146,6 +176,16 @@ impl Response {
146
176
}
147
177
148
178
/// Get the response as a Rune value decoded from JSON.
179
+ ///
180
+ /// ```rune,no_run
181
+ /// let client = http::Client::new();
182
+ ///
183
+ /// let response = client.get("http://example.com")
184
+ /// .send()
185
+ /// .await?;
186
+ ///
187
+ /// let response = response.json().await?;
188
+ /// ```
149
189
#[ rune:: function]
150
190
async fn json ( self ) -> Result < Value , Error > {
151
191
let text = self . response . json ( ) . await ?;
@@ -171,15 +211,34 @@ impl Response {
171
211
}
172
212
173
213
/// Get the status code of the response.
174
- #[ rune:: function]
214
+ #[ rune:: function( instance ) ]
175
215
fn status ( & self ) -> StatusCode {
176
216
let inner = self . response . status ( ) ;
177
217
StatusCode { inner }
178
218
}
219
+
220
+ /// Get the version of the response.
221
+ #[ rune:: function( instance) ]
222
+ fn version ( & self ) -> Version {
223
+ let inner = self . response . version ( ) ;
224
+ Version { inner }
225
+ }
226
+
227
+ /// Get the content-length of this response, if known.
228
+ ///
229
+ /// Reasons it may not be known:
230
+ ///
231
+ /// - The server didn't send a `content-length` header.
232
+ /// - The response is compressed and automatically decoded (thus changing
233
+ /// the actual decoded length).
234
+ #[ rune:: function( instance) ]
235
+ fn content_length ( & self ) -> Option < u64 > {
236
+ self . response . content_length ( )
237
+ }
179
238
}
180
239
181
240
/// An HTTP status code.
182
- #[ derive( Debug , Any ) ]
241
+ #[ derive( Debug , Any , PartialEq , Eq , PartialOrd , Ord ) ]
183
242
#[ rune( item = :: http) ]
184
243
pub struct StatusCode {
185
244
inner : reqwest:: StatusCode ,
@@ -190,6 +249,77 @@ impl StatusCode {
190
249
fn string_display ( & self , f : & mut Formatter ) -> VmResult < ( ) > {
191
250
rune:: vm_write!( f, "{}" , self . inner)
192
251
}
252
+
253
+ /// Returns the `Integer` corresponding to this `StatusCode`.
254
+ #[ rune:: function( instance) ]
255
+ #[ inline]
256
+ fn as_u16 ( & self ) -> u16 {
257
+ self . inner . as_u16 ( )
258
+ }
259
+
260
+ /// Returns a String representation of the `StatusCode`.
261
+ #[ rune:: function( instance) ]
262
+ #[ inline]
263
+ fn as_str ( & self ) -> String {
264
+ self . inner . as_str ( ) . to_owned ( )
265
+ }
266
+
267
+ /// Get the standardised `reason-phrase` for this status code.
268
+ #[ inline]
269
+ #[ rune:: function( instance) ]
270
+ fn canonical_reason ( & self ) -> Option < & ' static str > {
271
+ self . inner . canonical_reason ( )
272
+ }
273
+
274
+ /// Check if status is within 100-199.
275
+ #[ inline]
276
+ #[ rune:: function( instance) ]
277
+ fn is_informational ( & self ) -> bool {
278
+ self . inner . is_informational ( )
279
+ }
280
+
281
+ /// Check if status is within 200-299.
282
+ #[ inline]
283
+ #[ rune:: function( instance) ]
284
+ fn is_success ( & self ) -> bool {
285
+ self . inner . is_success ( )
286
+ }
287
+
288
+ /// Check if status is within 300-399.
289
+ #[ inline]
290
+ #[ rune:: function( instance) ]
291
+ fn is_redirection ( & self ) -> bool {
292
+ self . inner . is_redirection ( )
293
+ }
294
+
295
+ /// Check if status is within 400-499.
296
+ #[ inline]
297
+ #[ rune:: function( instance) ]
298
+ fn is_client_error ( & self ) -> bool {
299
+ self . inner . is_client_error ( )
300
+ }
301
+
302
+ /// Check if status is within 500-599.
303
+ #[ inline]
304
+ #[ rune:: function( instance) ]
305
+ fn is_server_error ( & self ) -> bool {
306
+ self . inner . is_server_error ( )
307
+ }
308
+ }
309
+
310
+ /// Represents a version of the HTTP spec.
311
+ #[ derive( Debug , Any , PartialEq , Eq , PartialOrd , Ord ) ]
312
+ #[ rune( item = :: http) ]
313
+ pub struct Version {
314
+ inner : reqwest:: Version ,
315
+ }
316
+
317
+ impl Version {
318
+ #[ rune:: function( instance, protocol = STRING_DISPLAY ) ]
319
+ fn string_display ( & self , f : & mut Formatter ) -> VmResult < ( ) > {
320
+ rune:: vm_write!( f, "{:?}" , self . inner) ;
321
+ VmResult :: Ok ( ( ) )
322
+ }
193
323
}
194
324
195
325
/// A builder to construct the properties of a Request.
@@ -239,6 +369,63 @@ impl RequestBuilder {
239
369
}
240
370
}
241
371
372
+ /// Enable basic authentication in the request.
373
+ ///
374
+ /// ```rune,no_run
375
+ /// let client = http::Client::new();
376
+ ///
377
+ /// let response = client.get("http://example.com")
378
+ /// .basic_auth("admin", Some("good password"))
379
+ /// .send()
380
+ /// .await?;
381
+ ///
382
+ /// let response = response.text().await?;
383
+ /// ```
384
+ #[ rune:: function]
385
+ fn basic_auth ( self , username : & str , password : Option < Ref < str > > ) -> Self {
386
+ Self {
387
+ request : self . request . basic_auth ( username, password. as_deref ( ) ) ,
388
+ }
389
+ }
390
+
391
+ /// Enable bearer authentication in the request.
392
+ ///
393
+ /// ```rune,no_run
394
+ /// let client = http::Client::new();
395
+ ///
396
+ /// let response = client.get("http://example.com")
397
+ /// .bearer_auth("A1B2C3D4E5")
398
+ /// .send()
399
+ /// .await?;
400
+ ///
401
+ /// let response = response.text().await?;
402
+ /// ```
403
+ #[ rune:: function]
404
+ fn bearer_auth ( self , token : & str ) -> Self {
405
+ Self {
406
+ request : self . request . bearer_auth ( token) ,
407
+ }
408
+ }
409
+
410
+ /// Set version in the request.
411
+ ///
412
+ /// ```rune,no_run
413
+ /// let client = http::Client::new();
414
+ ///
415
+ /// let response = client.get("http://example.com")
416
+ /// .version(Version::HTTP_2)
417
+ /// .send()
418
+ /// .await?;
419
+ ///
420
+ /// let response = response.text().await?;
421
+ /// ```
422
+ #[ rune:: function]
423
+ fn version ( self , version : Version ) -> Self {
424
+ Self {
425
+ request : self . request . version ( version. inner ) ,
426
+ }
427
+ }
428
+
242
429
/// Disable CORS on fetching the request.
243
430
///
244
431
/// This option is only effective with WebAssembly target.
@@ -312,7 +499,7 @@ impl Client {
312
499
///
313
500
/// let response = response.text().await?;
314
501
/// ```
315
- #[ rune:: function]
502
+ #[ rune:: function( instance ) ]
316
503
fn get ( & self , url : & str ) -> RequestBuilder {
317
504
RequestBuilder {
318
505
request : self . client . get ( url) ,
@@ -327,17 +514,97 @@ impl Client {
327
514
/// let client = http::Client::new();
328
515
///
329
516
/// let response = client.post("https://postman-echo.com/post")
330
- /// .body_bytes(b"Hello World ")
517
+ /// .body_bytes(b"My post data... ")
331
518
/// .send()
332
519
/// .await?;
333
520
///
334
521
/// let response = response.json().await?;
335
522
/// ```
336
- #[ rune:: function]
523
+ #[ rune:: function( instance ) ]
337
524
fn post ( & self , url : & str ) -> RequestBuilder {
338
525
let request = self . client . post ( url) ;
339
526
RequestBuilder { request }
340
527
}
528
+
529
+ /// Construct a builder to PUT to the given `url`.
530
+ ///
531
+ /// # Examples
532
+ ///
533
+ /// ```rune,no_run
534
+ /// let client = http::Client::new();
535
+ ///
536
+ /// let response = client.put("https://postman-echo.com/put")
537
+ /// .body_bytes(b"My put data...")
538
+ /// .send()
539
+ /// .await?;
540
+ ///
541
+ /// let response = response.json().await?;
542
+ /// ```
543
+ #[ rune:: function( instance) ]
544
+ fn put ( & self , url : & str ) -> RequestBuilder {
545
+ let request = self . client . put ( url) ;
546
+ RequestBuilder { request }
547
+ }
548
+
549
+ /// Construct a builder to PATCH to the given `url`.
550
+ ///
551
+ /// # Examples
552
+ ///
553
+ /// ```rune,no_run
554
+ /// let client = http::Client::new();
555
+ ///
556
+ /// let response = client.patch("https://postman-echo.com/patch")
557
+ /// .body_bytes(b"My patch data...")
558
+ /// .send()
559
+ /// .await?;
560
+ ///
561
+ /// let response = response.json().await?;
562
+ /// ```
563
+ #[ rune:: function( instance) ]
564
+ fn patch ( & self , url : & str ) -> RequestBuilder {
565
+ let request = self . client . patch ( url) ;
566
+ RequestBuilder { request }
567
+ }
568
+
569
+ /// Construct a builder to DELETE to the given `url`.
570
+ ///
571
+ /// # Examples
572
+ ///
573
+ /// ```rune,no_run
574
+ /// let client = http::Client::new();
575
+ ///
576
+ /// let response = client.delete("https://postman-echo.com/delete")
577
+ /// .body_bytes(b"My delete data...")
578
+ /// .send()
579
+ /// .await?;
580
+ ///
581
+ /// let response = response.json().await?;
582
+ /// ```
583
+ #[ rune:: function( instance) ]
584
+ fn delete ( & self , url : & str ) -> RequestBuilder {
585
+ let request = self . client . delete ( url) ;
586
+ RequestBuilder { request }
587
+ }
588
+
589
+ /// Construct a builder to HEAD to the given `url`.
590
+ ///
591
+ /// # Examples
592
+ ///
593
+ /// ```rune,no_run
594
+ /// let client = http::Client::new();
595
+ ///
596
+ /// let response = client.head("https://postman-echo.com/head")
597
+ /// .body_bytes(b"My head data...")
598
+ /// .send()
599
+ /// .await?;
600
+ ///
601
+ /// let response = response.json().await?;
602
+ /// ```
603
+ #[ rune:: function( instance) ]
604
+ fn head ( & self , url : & str ) -> RequestBuilder {
605
+ let request = self . client . head ( url) ;
606
+ RequestBuilder { request }
607
+ }
341
608
}
342
609
343
610
/// Shorthand for generating a get request.
0 commit comments