@@ -10,6 +10,12 @@ use std::future::Future;
10
10
/// An abstract HTTP client.
11
11
pub trait HttpClient {
12
12
/// Send an HTTP request and return the response.
13
+ #[ cfg( target_arch = "wasm32" ) ]
14
+ fn send_http (
15
+ & self ,
16
+ request : Request < Vec < u8 > > ,
17
+ ) -> impl Future < Output = core:: result:: Result < Response < Vec < u8 > > , Box < dyn std:: error:: Error + Send + Sync + ' static > > > ;
18
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
13
19
fn send_http (
14
20
& self ,
15
21
request : Request < Vec < u8 > > ,
@@ -27,18 +33,45 @@ pub trait XrpcClient: HttpClient {
27
33
fn base_uri ( & self ) -> String ;
28
34
/// Get the authentication token to use `Authorization` header.
29
35
#[ allow( unused_variables) ]
36
+ #[ cfg( target_arch = "wasm32" ) ]
37
+ fn authentication_token ( & self , is_refresh : bool ) -> impl Future < Output = Option < String > > {
38
+ async { None }
39
+ }
40
+ #[ allow( unused_variables) ]
41
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
30
42
fn authentication_token ( & self , is_refresh : bool ) -> impl Future < Output = Option < String > > + Send {
31
43
async { None }
32
44
}
33
45
/// Get the `atproto-proxy` header.
46
+ #[ cfg( target_arch = "wasm32" ) ]
47
+ fn atproto_proxy_header ( & self ) -> impl Future < Output = Option < String > > {
48
+ async { None }
49
+ }
50
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
34
51
fn atproto_proxy_header ( & self ) -> impl Future < Output = Option < String > > + Send {
35
52
async { None }
36
53
}
37
54
/// Get the `atproto-accept-labelers` header.
55
+ #[ cfg( target_arch = "wasm32" ) ]
56
+ fn atproto_accept_labelers_header ( & self ) -> impl Future < Output = Option < Vec < String > > > {
57
+ async { None }
58
+ }
59
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
38
60
fn atproto_accept_labelers_header ( & self ) -> impl Future < Output = Option < Vec < String > > > + Send {
39
61
async { None }
40
62
}
41
63
/// Send an XRPC request and return the response.
64
+ #[ cfg( target_arch = "wasm32" ) ]
65
+ fn send_xrpc < P , I , O , E > ( & self , request : & XrpcRequest < P , I > ) -> impl Future < Output = XrpcResult < O , E > >
66
+ where
67
+ P : Serialize + Send + Sync ,
68
+ I : Serialize + Send + Sync ,
69
+ O : DeserializeOwned + Send + Sync ,
70
+ E : DeserializeOwned + Send + Sync + Debug ,
71
+ {
72
+ send_xrpc ( self , request)
73
+ }
74
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
42
75
fn send_xrpc < P , I , O , E > ( & self , request : & XrpcRequest < P , I > ) -> impl Future < Output = XrpcResult < O , E > > + Send
43
76
where
44
77
P : Serialize + Send + Sync ,
@@ -47,63 +80,72 @@ pub trait XrpcClient: HttpClient {
47
80
E : DeserializeOwned + Send + Sync + Debug ,
48
81
Self : Sync ,
49
82
{
50
- async {
51
- let mut uri = format ! ( "{}/xrpc/{}" , self . base_uri( ) , request. nsid) ;
52
- // Query parameters
53
- if let Some ( p) = & request. parameters {
54
- serde_html_form:: to_string ( p) . map ( |qs| {
55
- uri += "?" ;
56
- uri += & qs;
57
- } ) ?;
58
- } ;
59
- let mut builder = Request :: builder ( ) . method ( & request. method ) . uri ( & uri) ;
60
- // Headers
61
- if let Some ( encoding) = & request. encoding {
62
- builder = builder. header ( Header :: ContentType , encoding) ;
63
- }
64
- if let Some ( token) = self
65
- . authentication_token (
66
- request. method == Method :: POST && request. nsid == NSID_REFRESH_SESSION ,
67
- )
68
- . await
69
- {
70
- builder = builder. header ( Header :: Authorization , format ! ( "Bearer {}" , token) ) ;
71
- }
72
- if let Some ( proxy) = self . atproto_proxy_header ( ) . await {
73
- builder = builder. header ( Header :: AtprotoProxy , proxy) ;
74
- }
75
- if let Some ( accept_labelers) = self . atproto_accept_labelers_header ( ) . await {
76
- builder = builder. header ( Header :: AtprotoAcceptLabelers , accept_labelers. join ( ", " ) ) ;
77
- }
78
- // Body
79
- let body = if let Some ( input) = & request. input {
80
- match input {
81
- InputDataOrBytes :: Data ( data) => serde_json:: to_vec ( & data) ?,
82
- InputDataOrBytes :: Bytes ( bytes) => bytes. clone ( ) ,
83
- }
84
- } else {
85
- Vec :: new ( )
86
- } ;
87
- // Send
88
- let ( parts, body) =
89
- self . send_http ( builder. body ( body) ?) . await . map_err ( Error :: HttpClient ) ?. into_parts ( ) ;
90
- if parts. status . is_success ( ) {
91
- if parts
92
- . headers
93
- . get ( http:: header:: CONTENT_TYPE )
94
- . and_then ( |value| value. to_str ( ) . ok ( ) )
95
- . map_or ( false , |content_type| content_type. starts_with ( "application/json" ) )
96
- {
97
- Ok ( OutputDataOrBytes :: Data ( serde_json:: from_slice ( & body) ?) )
98
- } else {
99
- Ok ( OutputDataOrBytes :: Bytes ( body) )
100
- }
101
- } else {
102
- Err ( Error :: XrpcResponse ( XrpcError {
103
- status : parts. status ,
104
- error : serde_json:: from_slice :: < XrpcErrorKind < E > > ( & body) . ok ( ) ,
105
- } ) )
106
- }
107
- }
83
+ send_xrpc ( self , request)
108
84
}
109
85
}
86
+
87
+ #[ inline( always) ]
88
+ async fn send_xrpc < P , I , O , E , C : XrpcClient + ?Sized > ( client : & C , request : & XrpcRequest < P , I > ) -> XrpcResult < O , E >
89
+ where
90
+ P : Serialize + Send + Sync ,
91
+ I : Serialize + Send + Sync ,
92
+ O : DeserializeOwned + Send + Sync ,
93
+ E : DeserializeOwned + Send + Sync + Debug ,
94
+ {
95
+ let mut uri = format ! ( "{}/xrpc/{}" , client. base_uri( ) , request. nsid) ;
96
+ // Query parameters
97
+ if let Some ( p) = & request. parameters {
98
+ serde_html_form:: to_string ( p) . map ( |qs| {
99
+ uri += "?" ;
100
+ uri += & qs;
101
+ } ) ?;
102
+ } ;
103
+ let mut builder = Request :: builder ( ) . method ( & request. method ) . uri ( & uri) ;
104
+ // Headers
105
+ if let Some ( encoding) = & request. encoding {
106
+ builder = builder. header ( Header :: ContentType , encoding) ;
107
+ }
108
+ if let Some ( token) = client
109
+ . authentication_token (
110
+ request. method == Method :: POST && request. nsid == NSID_REFRESH_SESSION ,
111
+ )
112
+ . await
113
+ {
114
+ builder = builder. header ( Header :: Authorization , format ! ( "Bearer {}" , token) ) ;
115
+ }
116
+ if let Some ( proxy) = client. atproto_proxy_header ( ) . await {
117
+ builder = builder. header ( Header :: AtprotoProxy , proxy) ;
118
+ }
119
+ if let Some ( accept_labelers) = client. atproto_accept_labelers_header ( ) . await {
120
+ builder = builder. header ( Header :: AtprotoAcceptLabelers , accept_labelers. join ( ", " ) ) ;
121
+ }
122
+ // Body
123
+ let body = if let Some ( input) = & request. input {
124
+ match input {
125
+ InputDataOrBytes :: Data ( data) => serde_json:: to_vec ( & data) ?,
126
+ InputDataOrBytes :: Bytes ( bytes) => bytes. clone ( ) ,
127
+ }
128
+ } else {
129
+ Vec :: new ( )
130
+ } ;
131
+ // Send
132
+ let ( parts, body) =
133
+ client. send_http ( builder. body ( body) ?) . await . map_err ( Error :: HttpClient ) ?. into_parts ( ) ;
134
+ if parts. status . is_success ( ) {
135
+ if parts
136
+ . headers
137
+ . get ( http:: header:: CONTENT_TYPE )
138
+ . and_then ( |value| value. to_str ( ) . ok ( ) )
139
+ . map_or ( false , |content_type| content_type. starts_with ( "application/json" ) )
140
+ {
141
+ Ok ( OutputDataOrBytes :: Data ( serde_json:: from_slice ( & body) ?) )
142
+ } else {
143
+ Ok ( OutputDataOrBytes :: Bytes ( body) )
144
+ }
145
+ } else {
146
+ Err ( Error :: XrpcResponse ( XrpcError {
147
+ status : parts. status ,
148
+ error : serde_json:: from_slice :: < XrpcErrorKind < E > > ( & body) . ok ( ) ,
149
+ } ) )
150
+ }
151
+ }
0 commit comments