2
2
//! [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen).
3
3
4
4
use crate :: * ;
5
- use futures:: { Future , IntoFuture } ;
6
- use log:: * ;
7
5
use std:: collections:: HashMap ;
8
- use thiserror:: * ;
9
- use wasm_bindgen:: { JsCast , JsValue } ;
10
- use wasm_bindgen_futures:: JsFuture ;
11
6
12
7
/// The main interface to the library.
13
8
///
@@ -19,39 +14,7 @@ use wasm_bindgen_futures::JsFuture;
19
14
pub struct Client {
20
15
endpoint : String ,
21
16
headers : HashMap < String , String > ,
22
- }
23
-
24
- /// All the ways a request can go wrong.
25
- ///
26
- /// not exhaustive
27
- #[ derive( Debug , Error , PartialEq ) ]
28
- pub enum ClientError {
29
- /// The body couldn't be built
30
- #[ error( "Request body is not a valid string" ) ]
31
- Body ,
32
- /// An error caused by window.fetch
33
- #[ error( "Network error" ) ]
34
- Network ( String ) ,
35
- /// Error in a dynamic JS cast that should have worked
36
- #[ error( "JS casting error" ) ]
37
- Cast ,
38
- /// No window object could be retrieved
39
- #[ error(
40
- "No Window object available - the client works only in a browser (non-worker) context"
41
- ) ]
42
- NoWindow ,
43
- /// Response shape does not match the generated code
44
- #[ error( "Response shape error" ) ]
45
- ResponseShape ,
46
- /// Response could not be converted to text
47
- #[ error( "Response conversion to text failed (Response.text threw)" ) ]
48
- ResponseText ,
49
- /// Exception thrown when building the request
50
- #[ error( "Error building the request" ) ]
51
- RequestError ,
52
- /// Other JS exception
53
- #[ error( "Unexpected JS exception" ) ]
54
- JsException ,
17
+ reqwest_client : reqwest:: Client ,
55
18
}
56
19
57
20
impl Client {
@@ -63,6 +26,7 @@ impl Client {
63
26
Client {
64
27
endpoint : endpoint. into ( ) ,
65
28
headers : HashMap :: new ( ) ,
29
+ reqwest_client : reqwest:: Client :: new ( ) ,
66
30
}
67
31
}
68
32
@@ -75,71 +39,25 @@ impl Client {
75
39
///
76
40
// Lint disabled: We can pass by value because it's always an empty struct.
77
41
#[ allow( clippy:: needless_pass_by_value) ]
78
- pub fn call < Q : GraphQLQuery + ' static > (
42
+ pub async fn call < Q : GraphQLQuery + ' static > (
79
43
& self ,
80
44
_query : Q ,
81
45
variables : Q :: Variables ,
82
- ) -> impl Future < Item = crate :: Response < Q :: ResponseData > , Error = ClientError > + ' static {
83
- // this can be removed when we convert to async/await
84
- let endpoint = self . endpoint . clone ( ) ;
85
- let custom_headers = self . headers . clone ( ) ;
86
-
87
- web_sys:: window ( )
88
- . ok_or_else ( || ClientError :: NoWindow )
89
- . into_future ( )
90
- . and_then ( move |window| {
91
- serde_json:: to_string ( & Q :: build_query ( variables) )
92
- . map_err ( |_| ClientError :: Body )
93
- . map ( move |body| ( window, body) )
94
- } )
95
- . and_then ( move |( window, body) | {
96
- let mut request_init = web_sys:: RequestInit :: new ( ) ;
97
- request_init
98
- . method ( "POST" )
99
- . body ( Some ( & JsValue :: from_str ( & body) ) ) ;
100
-
101
- web_sys:: Request :: new_with_str_and_init ( & endpoint, & request_init)
102
- . map_err ( |_| ClientError :: JsException )
103
- . map ( |request| ( window, request) )
104
- // "Request constructor threw");
105
- } )
106
- . and_then ( move |( window, request) | {
107
- let headers = request. headers ( ) ;
108
- headers
109
- . set ( "Content-Type" , "application/json" )
110
- . map_err ( |_| ClientError :: RequestError ) ?;
111
- headers
112
- . set ( "Accept" , "application/json" )
113
- . map_err ( |_| ClientError :: RequestError ) ?;
46
+ ) -> Result < crate :: Response < Q :: ResponseData > , reqwest:: Error > {
47
+ // TODO: remove the unwrap
48
+ // TODO: remove tests and test harness
49
+ // TODO: custom headers
50
+ let reqwest_response = self
51
+ . reqwest_client
52
+ . post ( & self . endpoint )
53
+ . header ( "Content-Type" , "application/json" )
54
+ . body ( serde_json:: to_string ( & Q :: build_query ( variables) ) . unwrap ( ) )
55
+ . send ( )
56
+ . await ?;
114
57
115
- for ( header_name, header_value) in custom_headers. iter ( ) {
116
- headers
117
- . set ( header_name, header_value)
118
- . map_err ( |_| ClientError :: RequestError ) ?;
119
- }
58
+ let text_response = reqwest_response. text ( ) . await ?;
120
59
121
- Ok ( ( window, request) )
122
- } )
123
- . and_then ( move |( window, request) | {
124
- JsFuture :: from ( window. fetch_with_request ( & request) )
125
- . map_err ( |err| ClientError :: Network ( js_sys:: Error :: from ( err) . message ( ) . into ( ) ) )
126
- } )
127
- . and_then ( move |res| {
128
- debug ! ( "response: {:?}" , res) ;
129
- res. dyn_into :: < web_sys:: Response > ( )
130
- . map_err ( |_| ClientError :: Cast )
131
- } )
132
- . and_then ( move |cast_response| {
133
- cast_response. text ( ) . map_err ( |_| ClientError :: ResponseText )
134
- } )
135
- . and_then ( move |text_promise| {
136
- JsFuture :: from ( text_promise) . map_err ( |_| ClientError :: ResponseText )
137
- } )
138
- . and_then ( |text| {
139
- let response_text = text. as_string ( ) . unwrap_or_default ( ) ;
140
- debug ! ( "response text as string: {:?}" , response_text) ;
141
- serde_json:: from_str ( & response_text) . map_err ( |_| ClientError :: ResponseShape )
142
- } )
60
+ Ok ( serde_json:: from_str ( & text_response) . unwrap ( ) )
143
61
}
144
62
}
145
63
0 commit comments