• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2025 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #![cfg(all(feature = "async", feature = "tokio_base", not(feature = "__tls")))]
15 
16 mod common;
17 
18 use std::convert::Infallible;
19 
20 use ylong_http::response::status::StatusCode;
21 use ylong_http_client::async_impl::{Body, Client, HttpBody, Request, Response};
22 use ylong_http_client::{ConnDetail, ErrorKind, HttpClientError, Interceptor};
23 
24 use crate::common::init_test_work_runtime;
25 
server_fn( _req: hyper::Request<hyper::Body>, ) -> Result<hyper::Response<hyper::Body>, Infallible>26 async fn server_fn(
27     _req: hyper::Request<hyper::Body>,
28 ) -> Result<hyper::Response<hyper::Body>, Infallible> {
29     let response = hyper::Response::builder()
30         .status(hyper::StatusCode::OK)
31         .body(hyper::Body::empty())
32         .expect("build hyper response failed");
33     Ok(response)
34 }
35 
server_fn_redirect( req: hyper::Request<hyper::Body>, ) -> Result<hyper::Response<hyper::Body>, Infallible>36 async fn server_fn_redirect(
37     req: hyper::Request<hyper::Body>,
38 ) -> Result<hyper::Response<hyper::Body>, Infallible> {
39     use hyper::body::HttpBody;
40     let mut body = req.into_body();
41 
42     let mut buf = vec![];
43     loop {
44         match body.data().await {
45             None => {
46                 break;
47             }
48             Some(Ok(bytes)) => buf.extend_from_slice(bytes.as_ref()),
49             Some(Err(_e)) => {
50                 panic!("server read request body data occurs error");
51             }
52         }
53     }
54     let redirect_addr = format!("127.0.0.1:{}", std::str::from_utf8(&buf).unwrap());
55     let response = hyper::Response::builder()
56         .header("Location", redirect_addr)
57         .status(hyper::StatusCode::TEMPORARY_REDIRECT)
58         .body(hyper::Body::empty())
59         .expect("build hyper response failed");
60     Ok(response)
61 }
62 
63 macro_rules! interceptor_test {
64     (
65         $interceptor: ident,
66         $service_fn: ident,
67         $version: literal,
68         Success;
69     ) => {
70         define_service_handle!(HTTP;);
71 
72         let rt = init_test_work_runtime(4);
73 
74         let mut handle = rt.block_on(async move {
75             let mut handle = start_http_server!(HTTP; $service_fn);
76             handle.server_start.recv().await.unwrap();
77             handle
78         });
79 
80         let client = Client::builder();
81         let client = match $version {
82             #[cfg(feature = "http1_1")]
83             "HTTP/1.1" => client.http1_only(),
84             #[cfg(feature = "http2")]
85             "HTTP/2.0" => client.http2_prior_knowledge(),
86             _ => client
87         };
88         let client = client
89             .interceptor($interceptor)
90             .build()
91             .expect("Build Client failed.");
92 
93         let request = Request::builder()
94             .url(format!("{}:{}", "127.0.0.1", handle.port).as_str())
95             .version($version)
96             .method("GET")
97             .body(Body::empty())
98             .expect("Client build Request failed.");
99 
100         rt.block_on(async move {
101             let response = client.request(request).await.expect("get response failed");
102             assert_eq!(response.status(), StatusCode::OK);
103 
104             handle.client_shutdown.send(()).await.unwrap();
105             handle.server_shutdown.recv().await.unwrap();
106         })
107     };
108     (
109         $interceptor: ident,
110         $service_fn: ident,
111         $version: literal,
112         Fail;
113     ) => {
114         define_service_handle!(HTTP;);
115 
116         let rt = init_test_work_runtime(4);
117 
118         let handle = rt.block_on(async move {
119             let mut handle = start_http_server!(HTTP; $service_fn);
120             handle.server_start.recv().await.unwrap();
121             handle
122         });
123 
124         let client = Client::builder();
125         let client = match $version {
126             #[cfg(feature = "http1_1")]
127             "HTTP/1.1" => client.http1_only(),
128             #[cfg(feature = "http2")]
129             "HTTP/2.0" => client.http2_prior_knowledge(),
130             _ => client
131         };
132         let client = client
133             .interceptor($interceptor)
134             .build()
135             .expect("Build Client failed.");
136 
137         let request = Request::builder()
138             .url(format!("{}:{}", "127.0.0.1", handle.port).as_str())
139             .version($version)
140             .method("GET")
141             .body(Body::empty())
142             .expect("Client build Request failed.");
143 
144         rt.block_on(async move {
145             let response = client.request(request).await;
146             assert!(response.is_err());
147             assert_eq!(response.err().unwrap().error_kind(), ErrorKind::UserAborted);
148 
149             handle.client_shutdown.send(()).await.unwrap();
150         })
151     };
152 }
153 
154 #[test]
155 #[cfg(feature = "http1_1")]
sdv_client_request_interceptor_http1_ok()156 fn sdv_client_request_interceptor_http1_ok() {
157     struct ExampleInterceptor;
158     impl Interceptor for ExampleInterceptor {}
159 
160     interceptor_test!(ExampleInterceptor, server_fn, "HTTP/1.1", Success;);
161 }
162 
163 #[test]
164 #[cfg(feature = "http1_1")]
sdv_client_request_interceptor_http1_connection()165 fn sdv_client_request_interceptor_http1_connection() {
166     struct ExampleInterceptor;
167     impl Interceptor for ExampleInterceptor {
168         fn intercept_connection(&self, _info: ConnDetail) -> Result<(), HttpClientError> {
169             Err(HttpClientError::user_aborted())
170         }
171     }
172 
173     interceptor_test!(ExampleInterceptor, server_fn, "HTTP/1.1", Fail;);
174 }
175 
176 #[test]
177 #[cfg(feature = "http1_1")]
sdv_client_request_interceptor_http1_input()178 fn sdv_client_request_interceptor_http1_input() {
179     struct ExampleInterceptor;
180     impl Interceptor for ExampleInterceptor {
181         fn intercept_input(&self, _bytes: &[u8]) -> Result<(), HttpClientError> {
182             Err(HttpClientError::user_aborted())
183         }
184     }
185 
186     interceptor_test!(ExampleInterceptor, server_fn, "HTTP/1.1", Fail;);
187 }
188 
189 #[test]
190 #[cfg(feature = "http1_1")]
sdv_client_request_interceptor_http1_output()191 fn sdv_client_request_interceptor_http1_output() {
192     struct ExampleInterceptor;
193     impl Interceptor for ExampleInterceptor {
194         fn intercept_output(&self, _bytes: &[u8]) -> Result<(), HttpClientError> {
195             Err(HttpClientError::user_aborted())
196         }
197     }
198 
199     interceptor_test!(ExampleInterceptor, server_fn, "HTTP/1.1", Fail;);
200 }
201 
202 #[test]
203 #[cfg(feature = "http1_1")]
sdv_client_request_interceptor_http1_request()204 fn sdv_client_request_interceptor_http1_request() {
205     struct ExampleInterceptor;
206     impl Interceptor for ExampleInterceptor {
207         fn intercept_request(&self, _request: &Request) -> Result<(), HttpClientError> {
208             Err(HttpClientError::user_aborted())
209         }
210     }
211 
212     interceptor_test!(ExampleInterceptor, server_fn, "HTTP/1.1", Fail;);
213 }
214 
215 #[test]
216 #[cfg(feature = "http1_1")]
sdv_client_request_interceptor_http1_response()217 fn sdv_client_request_interceptor_http1_response() {
218     struct ExampleInterceptor;
219     impl Interceptor for ExampleInterceptor {
220         fn intercept_response(&self, _response: &Response) -> Result<(), HttpClientError> {
221             Err(HttpClientError::user_aborted())
222         }
223     }
224 
225     interceptor_test!(ExampleInterceptor, server_fn, "HTTP/1.1", Fail;);
226 }
227 
228 #[test]
229 #[cfg(feature = "http1_1")]
sdv_client_request_interceptor_http1_retry()230 fn sdv_client_request_interceptor_http1_retry() {
231     struct ExampleInterceptor;
232     impl Interceptor for ExampleInterceptor {
233         fn intercept_connection(&self, _info: ConnDetail) -> Result<(), HttpClientError> {
234             Err(HttpClientError::other("other"))
235         }
236         fn intercept_retry(&self, _error: &HttpClientError) -> Result<(), HttpClientError> {
237             Err(HttpClientError::user_aborted())
238         }
239     }
240 
241     define_service_handle!( HTTP ; );
242     let rt = init_test_work_runtime(4);
243     let handle = rt.block_on(async move {
244         let mut handle = start_http_server!( HTTP ; server_fn );
245         handle.server_start.recv().await.unwrap();
246         handle
247     });
248     let client = Client::builder()
249         .retry(ylong_http_client::Retry::new(2).unwrap())
250         .interceptor(ExampleInterceptor)
251         .build()
252         .expect("Build Client failed.");
253     let request = Request::builder()
254         .url(format!("{}:{}", "127.0.0.1", handle.port).as_str())
255         .version("HTTP/1.1")
256         .method("GET")
257         .body(Body::empty())
258         .expect("Client build Request failed.");
259     rt.block_on(async move {
260         let response = client.request(request).await;
261         assert!(response.is_err());
262         assert_eq!(response.err().unwrap().error_kind(), ErrorKind::UserAborted);
263 
264         handle.client_shutdown.send(()).await.unwrap();
265     })
266 }
267 
268 #[test]
269 #[cfg(feature = "http1_1")]
sdv_client_request_interceptor_http1_redirect_request()270 fn sdv_client_request_interceptor_http1_redirect_request() {
271     struct ExampleInterceptor;
272     impl Interceptor for ExampleInterceptor {
273         fn intercept_redirect_request(&self, _request: &Request) -> Result<(), HttpClientError> {
274             Err(HttpClientError::user_aborted())
275         }
276     }
277 
278     interceptor_test!(ExampleInterceptor, server_fn_redirect, "HTTP/1.1", Fail;);
279 }
280 
281 #[test]
282 #[cfg(feature = "http1_1")]
sdv_client_request_interceptor_http1_redirect_response()283 fn sdv_client_request_interceptor_http1_redirect_response() {
284     struct ExampleInterceptor;
285     impl Interceptor for ExampleInterceptor {
286         fn intercept_redirect_response(
287             &self,
288             _response: &ylong_http::response::Response<HttpBody>,
289         ) -> Result<(), HttpClientError> {
290             Err(HttpClientError::user_aborted())
291         }
292     }
293 
294     define_service_handle!( HTTP ; );
295     let rt = init_test_work_runtime(4);
296     let (handle1, mut handle2) = rt.block_on(async move {
297         let mut handle1 = start_http_server!( HTTP ; server_fn_redirect );
298         let mut handle2 = start_http_server!( HTTP ; server_fn );
299         handle1.server_start.recv().await.unwrap();
300         handle2.server_start.recv().await.unwrap();
301         (handle1, handle2)
302     });
303     let client = Client::builder()
304         .interceptor(ExampleInterceptor)
305         .build()
306         .expect("Build Client failed.");
307     let request = Request::builder()
308         .url(format!("{}:{}", "127.0.0.1", handle1.port).as_str())
309         .version("HTTP/1.1")
310         .method("GET")
311         .body(Body::slice(handle2.port.to_string().as_str()))
312         .expect("Client build Request failed.");
313     rt.block_on(async move {
314         let response = client.request(request).await;
315         assert!(response.is_err());
316         assert_eq!(response.err().unwrap().error_kind(), ErrorKind::UserAborted);
317 
318         handle1.client_shutdown.send(()).await.unwrap();
319         handle2.client_shutdown.send(()).await.unwrap();
320         handle2.server_shutdown.recv().await.unwrap();
321     })
322 }
323 
324 #[test]
325 #[cfg(feature = "http2")]
sdv_client_request_interceptor_http2_ok()326 fn sdv_client_request_interceptor_http2_ok() {
327     struct ExampleInterceptor;
328     impl Interceptor for ExampleInterceptor {}
329 
330     interceptor_test!(ExampleInterceptor, server_fn, "HTTP/2.0", Success;);
331 }
332 
333 #[test]
334 #[cfg(feature = "http2")]
sdv_client_request_interceptor_http2_connection()335 fn sdv_client_request_interceptor_http2_connection() {
336     struct ExampleInterceptor;
337     impl Interceptor for ExampleInterceptor {
338         fn intercept_connection(&self, _info: ConnDetail) -> Result<(), HttpClientError> {
339             Err(HttpClientError::user_aborted())
340         }
341     }
342 
343     interceptor_test!(ExampleInterceptor, server_fn, "HTTP/2.0", Fail;);
344 }
345 
346 #[test]
347 #[cfg(feature = "http2")]
sdv_client_request_interceptor_http2_request()348 fn sdv_client_request_interceptor_http2_request() {
349     struct ExampleInterceptor;
350     impl Interceptor for ExampleInterceptor {
351         fn intercept_request(&self, _request: &Request) -> Result<(), HttpClientError> {
352             Err(HttpClientError::user_aborted())
353         }
354     }
355 
356     interceptor_test!(ExampleInterceptor, server_fn, "HTTP/2.0", Fail;);
357 }
358 
359 #[test]
360 #[cfg(feature = "http2")]
sdv_client_request_interceptor_http2_response()361 fn sdv_client_request_interceptor_http2_response() {
362     struct ExampleInterceptor;
363     impl Interceptor for ExampleInterceptor {
364         fn intercept_response(&self, _response: &Response) -> Result<(), HttpClientError> {
365             Err(HttpClientError::user_aborted())
366         }
367     }
368 
369     interceptor_test!(ExampleInterceptor, server_fn, "HTTP/2.0", Fail;);
370 }
371 
372 #[test]
373 #[cfg(feature = "http2")]
sdv_client_request_interceptor_http2_retry()374 fn sdv_client_request_interceptor_http2_retry() {
375     struct ExampleInterceptor;
376     impl Interceptor for ExampleInterceptor {
377         fn intercept_connection(&self, _info: ConnDetail) -> Result<(), HttpClientError> {
378             Err(HttpClientError::other("other"))
379         }
380         fn intercept_retry(&self, _error: &HttpClientError) -> Result<(), HttpClientError> {
381             Err(HttpClientError::user_aborted())
382         }
383     }
384 
385     define_service_handle!( HTTP ; );
386     let rt = init_test_work_runtime(4);
387     let handle = rt.block_on(async move {
388         let mut handle = start_http_server!( HTTP ; server_fn );
389         handle.server_start.recv().await.unwrap();
390         handle
391     });
392     let client = Client::builder()
393         .http2_prior_knowledge()
394         .retry(ylong_http_client::Retry::new(2).unwrap())
395         .interceptor(ExampleInterceptor)
396         .build()
397         .expect("Build Client failed.");
398     let request = Request::builder()
399         .url(format!("{}:{}", "127.0.0.1", handle.port).as_str())
400         .version("HTTP/2.0")
401         .method("GET")
402         .body(Body::empty())
403         .expect("Client build Request failed.");
404     rt.block_on(async move {
405         let response = client.request(request).await;
406         assert!(response.is_err());
407         assert_eq!(response.err().unwrap().error_kind(), ErrorKind::UserAborted);
408 
409         handle.client_shutdown.send(()).await.unwrap();
410     })
411 }
412 
413 #[test]
414 #[cfg(feature = "http2")]
sdv_client_request_interceptor_http2_redirect_request()415 fn sdv_client_request_interceptor_http2_redirect_request() {
416     struct ExampleInterceptor;
417     impl Interceptor for ExampleInterceptor {
418         fn intercept_redirect_request(&self, _request: &Request) -> Result<(), HttpClientError> {
419             Err(HttpClientError::user_aborted())
420         }
421     }
422 
423     interceptor_test!(ExampleInterceptor, server_fn_redirect, "HTTP/2.0", Fail;);
424 }
425 
426 #[test]
427 #[cfg(feature = "http2")]
sdv_client_request_interceptor_http2_redirect_response()428 fn sdv_client_request_interceptor_http2_redirect_response() {
429     struct ExampleInterceptor;
430     impl Interceptor for ExampleInterceptor {
431         fn intercept_redirect_response(
432             &self,
433             _response: &ylong_http::response::Response<HttpBody>,
434         ) -> Result<(), HttpClientError> {
435             Err(HttpClientError::user_aborted())
436         }
437     }
438 
439     define_service_handle!( HTTP ; );
440     let rt = init_test_work_runtime(4);
441     let (handle1, mut handle2) = rt.block_on(async move {
442         let mut handle1 = start_http_server!( HTTP ; server_fn_redirect );
443         let mut handle2 = start_http_server!( HTTP ; server_fn );
444         handle1.server_start.recv().await.unwrap();
445         handle2.server_start.recv().await.unwrap();
446         (handle1, handle2)
447     });
448     let client = Client::builder()
449         .http2_prior_knowledge()
450         .interceptor(ExampleInterceptor)
451         .build()
452         .expect("Build Client failed.");
453     let request = Request::builder()
454         .url(format!("{}:{}", "127.0.0.1", handle1.port).as_str())
455         .version("HTTP/2.0")
456         .method("GET")
457         .body(Body::slice(handle2.port.to_string().as_str()))
458         .expect("Client build Request failed.");
459     rt.block_on(async move {
460         let response = client.request(request).await;
461         assert!(response.is_err());
462         assert_eq!(response.err().unwrap().error_kind(), ErrorKind::UserAborted);
463 
464         handle1.client_shutdown.send(()).await.unwrap();
465         handle2.client_shutdown.send(()).await.unwrap();
466         handle2.server_shutdown.recv().await.unwrap();
467     })
468 }
469