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