22//! [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen).
33
44use crate :: * ;
5- use futures:: { Future , IntoFuture } ;
6- use log:: * ;
75use std:: collections:: HashMap ;
8- use thiserror:: * ;
9- use wasm_bindgen:: { JsCast , JsValue } ;
10- use wasm_bindgen_futures:: JsFuture ;
116
127/// The main interface to the library.
138///
@@ -19,39 +14,7 @@ use wasm_bindgen_futures::JsFuture;
1914pub struct Client {
2015 endpoint : String ,
2116 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 ,
5518}
5619
5720impl Client {
@@ -63,6 +26,7 @@ impl Client {
6326 Client {
6427 endpoint : endpoint. into ( ) ,
6528 headers : HashMap :: new ( ) ,
29+ reqwest_client : reqwest:: Client :: new ( ) ,
6630 }
6731 }
6832
@@ -75,71 +39,25 @@ impl Client {
7539 ///
7640 // Lint disabled: We can pass by value because it's always an empty struct.
7741 #[ allow( clippy:: needless_pass_by_value) ]
78- pub fn call < Q : GraphQLQuery + ' static > (
42+ pub async fn call < Q : GraphQLQuery + ' static > (
7943 & self ,
8044 _query : Q ,
8145 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 ?;
11457
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 ?;
12059
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 ( ) )
14361 }
14462}
14563
0 commit comments