1
1
use async_trait:: async_trait;
2
- use lazy_static:: lazy_static;
3
2
use meilisearch_sdk:: errors:: Error ;
4
3
use meilisearch_sdk:: request:: { parse_response, HttpClient , Method } ;
5
4
use meilisearch_sdk:: { client:: * , settings:: Settings } ;
6
5
use serde:: de:: DeserializeOwned ;
7
6
use serde:: { Deserialize , Serialize } ;
8
- use serde_json:: to_string;
9
7
use std:: fmt;
10
8
use std:: io:: stdin;
11
9
12
- lazy_static ! {
13
- static ref CLIENT : Client < ReqwestClient > =
14
- Client :: new_with_client ( "http://localhost:7700" , Some ( "masterKey" ) , ReqwestClient ) ;
10
+ # [ derive ( Debug , Clone ) ]
11
+ pub struct AwcClient {
12
+ api_key : Option < String > ,
15
13
}
16
14
17
- #[ derive( Debug , Clone , Serialize ) ]
18
- pub struct ReqwestClient ;
15
+ impl AwcClient {
16
+ pub fn new ( api_key : Option < & str > ) -> Result < Self , Error > {
17
+ Ok ( AwcClient {
18
+ api_key : api_key. map ( |key| key. to_string ( ) ) ,
19
+ } )
20
+ }
21
+ }
19
22
20
23
#[ async_trait( ?Send ) ]
21
- impl HttpClient for ReqwestClient {
22
- async fn request < Query , Body , Output > (
24
+ impl HttpClient for AwcClient {
25
+ async fn stream_request <
26
+ Query : Serialize + Send + Sync ,
27
+ Body : futures:: AsyncRead + Send + Sync + ' static ,
28
+ Output : DeserializeOwned + ' static ,
29
+ > (
23
30
& self ,
24
31
url : & str ,
25
32
method : Method < Query , Body > ,
33
+ content_type : & str ,
26
34
expected_status_code : u16 ,
27
- ) -> Result < Output , Error >
28
- where
29
- Query : Serialize + Send + Sync ,
30
- Body : Serialize + Send + Sync ,
31
- Output : DeserializeOwned + ' static + Send ,
32
- {
33
- let response = match & method {
34
- Method :: Get { query } => {
35
- let url = add_query_parameters ( url, query) ?;
36
- let client = reqwest:: Client :: new ( ) ;
37
- let builder = client. request ( reqwest:: Method :: GET , url. as_str ( ) ) ;
38
- let req = builder. build ( ) . unwrap ( ) ;
39
- client. execute ( req) . await . unwrap ( )
40
- }
41
- Method :: Post { query, body } => {
42
- let url = add_query_parameters ( url, query) ?;
43
- let client = reqwest:: Client :: new ( ) ;
44
- let mut builder = client. request ( reqwest:: Method :: POST , url. as_str ( ) ) ;
45
- builder = builder. header ( reqwest:: header:: CONTENT_TYPE , "application/json" ) ;
46
- let req = builder. body ( to_string ( body) . unwrap ( ) ) . build ( ) . unwrap ( ) ;
47
- client. execute ( req) . await . unwrap ( )
48
- }
49
- Method :: Patch { query, body } => {
50
- let url = add_query_parameters ( url, query) ?;
51
- let client = reqwest:: Client :: new ( ) ;
52
- let mut builder = client. request ( reqwest:: Method :: PATCH , url. as_str ( ) ) ;
53
- builder = builder. header ( reqwest:: header:: CONTENT_TYPE , "application/json" ) ;
54
- let req = builder. body ( to_string ( body) . unwrap ( ) ) . build ( ) . unwrap ( ) ;
55
- client. execute ( req) . await . unwrap ( )
56
- }
57
- Method :: Put { query, body } => {
58
- let url = add_query_parameters ( url, query) ?;
59
- let client = reqwest:: Client :: new ( ) ;
60
- let mut builder = client. request ( reqwest:: Method :: PUT , url. as_str ( ) ) ;
61
- builder = builder. header ( reqwest:: header:: CONTENT_TYPE , "application/json" ) ;
62
- let req = builder. body ( to_string ( body) . unwrap ( ) ) . build ( ) . unwrap ( ) ;
63
- client. execute ( req) . await . unwrap ( )
64
- }
65
- Method :: Delete { query } => {
66
- let url = add_query_parameters ( url, query) ?;
67
- let client = reqwest:: Client :: new ( ) ;
68
- let mut builder = client. request ( reqwest:: Method :: DELETE , url. as_str ( ) ) ;
69
- builder = builder. header ( reqwest:: header:: CONTENT_TYPE , "application/json" ) ;
70
- let req = builder. build ( ) . unwrap ( ) ;
71
- client. execute ( req) . await . unwrap ( )
72
- }
35
+ ) -> Result < Output , Error > {
36
+ let mut builder = awc:: ClientBuilder :: new ( ) ;
37
+ if let Some ( ref api_key) = self . api_key {
38
+ builder = builder. bearer_auth ( api_key) ;
39
+ }
40
+ builder = builder. add_default_header ( ( "User-Agent" , "Rust client with Awc" ) ) ;
41
+ let client = builder. finish ( ) ;
42
+
43
+ let query = method. query ( ) ;
44
+ let query = yaup:: to_string ( query) ?;
45
+
46
+ let url = if query. is_empty ( ) {
47
+ url. to_string ( )
48
+ } else {
49
+ format ! ( "{url}?{query}" )
73
50
} ;
74
51
75
- let status = response. status ( ) . as_u16 ( ) ;
52
+ let url = add_query_parameters ( & url, method. query ( ) ) ?;
53
+ let request = client. request ( verb ( & method) , & url) ;
76
54
77
- let mut body = response. text ( ) . await . unwrap ( ) ;
55
+ let mut response = if let Some ( body) = method. into_body ( ) {
56
+ let reader = tokio_util:: compat:: FuturesAsyncReadCompatExt :: compat ( body) ;
57
+ let stream = tokio_util:: io:: ReaderStream :: new ( reader) ;
58
+ request
59
+ . content_type ( content_type)
60
+ . send_stream ( stream)
61
+ . await
62
+ . map_err ( |err| Error :: Other ( Box :: new ( err) ) ) ?
63
+ } else {
64
+ request
65
+ . send ( )
66
+ . await
67
+ . map_err ( |err| Error :: Other ( Box :: new ( err) ) ) ?
68
+ } ;
69
+
70
+ let status = response. status ( ) . as_u16 ( ) ;
71
+ let mut body = String :: from_utf8 (
72
+ response
73
+ . body ( )
74
+ . await
75
+ . map_err ( |err| Error :: Other ( Box :: new ( err) ) ) ?
76
+ . to_vec ( ) ,
77
+ )
78
+ . map_err ( |err| Error :: Other ( Box :: new ( err) ) ) ?;
78
79
79
80
if body. is_empty ( ) {
80
81
body = "null" . to_string ( ) ;
81
82
}
82
83
83
84
parse_response ( status, expected_status_code, & body, url. to_string ( ) )
84
85
}
85
-
86
- async fn stream_request <
87
- Query : Serialize + Send + Sync ,
88
- Body : futures:: AsyncRead + Send + Sync + ' static ,
89
- Output : DeserializeOwned + ' static ,
90
- > (
91
- & self ,
92
- _url : & str ,
93
- _method : Method < Query , Body > ,
94
- _content_type : & str ,
95
- _expected_status_code : u16 ,
96
- ) -> Result < Output , Error > {
97
- unimplemented ! ( "stream_request is not implemented for ReqwestClient" )
98
- }
99
86
}
100
87
101
- #[ tokio :: main]
88
+ #[ actix_rt :: main]
102
89
async fn main ( ) {
90
+ let http_client = AwcClient :: new ( Some ( "masterKey" ) ) . unwrap ( ) ;
91
+ let client = Client :: new_with_client ( "http://localhost:7700" , Some ( "masterKey" ) , http_client) ;
92
+
103
93
// build the index
104
- build_index ( ) . await ;
94
+ build_index ( & client ) . await ;
105
95
106
96
// enter in search queries or quit
107
97
loop {
@@ -116,18 +106,18 @@ async fn main() {
116
106
break ;
117
107
}
118
108
_ => {
119
- search ( input_string. trim ( ) ) . await ;
109
+ search ( & client , input_string. trim ( ) ) . await ;
120
110
}
121
111
}
122
112
}
123
113
// get rid of the index at the end, doing this only so users don't have the index without knowing
124
- let _ = CLIENT . delete_index ( "clothes" ) . await . unwrap ( ) ;
114
+ let _ = client . delete_index ( "clothes" ) . await . unwrap ( ) ;
125
115
}
126
116
127
- async fn search ( query : & str ) {
117
+ async fn search ( client : & Client < AwcClient > , query : & str ) {
128
118
// make the search query, which excutes and serializes hits into the
129
119
// ClothesDisplay struct
130
- let query_results = CLIENT
120
+ let query_results = client
131
121
. index ( "clothes" )
132
122
. search ( )
133
123
. with_query ( query)
@@ -147,7 +137,7 @@ async fn search(query: &str) {
147
137
}
148
138
}
149
139
150
- async fn build_index ( ) {
140
+ async fn build_index ( client : & Client < AwcClient > ) {
151
141
// reading and parsing the file
152
142
let content = include_str ! ( "../assets/clothes.json" ) ;
153
143
@@ -177,12 +167,12 @@ async fn build_index() {
177
167
. with_synonyms ( synonyms) ;
178
168
179
169
//add the settings to the index
180
- let result = CLIENT
170
+ let result = client
181
171
. index ( "clothes" )
182
172
. set_settings ( & settings)
183
173
. await
184
174
. unwrap ( )
185
- . wait_for_completion ( & CLIENT , None , None )
175
+ . wait_for_completion ( client , None , None )
186
176
. await
187
177
. unwrap ( ) ;
188
178
@@ -194,12 +184,12 @@ async fn build_index() {
194
184
}
195
185
196
186
// add the documents
197
- let result = CLIENT
187
+ let result = client
198
188
. index ( "clothes" )
199
189
. add_or_update ( & clothes, Some ( "id" ) )
200
190
. await
201
191
. unwrap ( )
202
- . wait_for_completion ( & CLIENT , None , None )
192
+ . wait_for_completion ( client , None , None )
203
193
. await
204
194
. unwrap ( ) ;
205
195
@@ -255,3 +245,13 @@ fn add_query_parameters<Query: Serialize>(url: &str, query: &Query) -> Result<St
255
245
Ok ( format ! ( "{url}?{query}" ) )
256
246
}
257
247
}
248
+
249
+ fn verb < Q , B > ( method : & Method < Q , B > ) -> awc:: http:: Method {
250
+ match method {
251
+ Method :: Get { .. } => awc:: http:: Method :: GET ,
252
+ Method :: Delete { .. } => awc:: http:: Method :: DELETE ,
253
+ Method :: Post { .. } => awc:: http:: Method :: POST ,
254
+ Method :: Put { .. } => awc:: http:: Method :: PUT ,
255
+ Method :: Patch { .. } => awc:: http:: Method :: PATCH ,
256
+ }
257
+ }
0 commit comments