1 #![cfg(not(target_arch = "wasm32"))]
2 mod support;
3 use support::*;
4 
5 use std::time::Duration;
6 
7 #[tokio::test]
client_timeout()8 async fn client_timeout() {
9     let _ = env_logger::try_init();
10 
11     let server = server::http(move |_req| {
12         async {
13             // delay returning the response
14             tokio::time::delay_for(Duration::from_secs(2)).await;
15             http::Response::default()
16         }
17     });
18 
19     let client = reqwest::Client::builder()
20         .timeout(Duration::from_millis(500))
21         .build()
22         .unwrap();
23 
24     let url = format!("http://{}/slow", server.addr());
25 
26     let res = client.get(&url).send().await;
27 
28     let err = res.unwrap_err();
29 
30     assert!(err.is_timeout());
31     assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));
32 }
33 
34 #[tokio::test]
request_timeout()35 async fn request_timeout() {
36     let _ = env_logger::try_init();
37 
38     let server = server::http(move |_req| {
39         async {
40             // delay returning the response
41             tokio::time::delay_for(Duration::from_secs(2)).await;
42             http::Response::default()
43         }
44     });
45 
46     let client = reqwest::Client::builder().build().unwrap();
47 
48     let url = format!("http://{}/slow", server.addr());
49 
50     let res = client
51         .get(&url)
52         .timeout(Duration::from_millis(500))
53         .send()
54         .await;
55 
56     let err = res.unwrap_err();
57 
58     if cfg!(not(target_arch = "wasm32")) {
59         assert!(err.is_timeout() && !err.is_connect());
60     } else {
61         assert!(err.is_timeout());
62     }
63     assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));
64 }
65 
66 #[cfg(not(target_arch = "wasm32"))]
67 #[tokio::test]
connect_timeout()68 async fn connect_timeout() {
69     let _ = env_logger::try_init();
70 
71     let client = reqwest::Client::builder()
72         .connect_timeout(Duration::from_millis(100))
73         .build()
74         .unwrap();
75 
76     let url = format!("http://10.255.255.1:81/slow");
77 
78     let res = client
79         .get(&url)
80         .timeout(Duration::from_millis(1000))
81         .send()
82         .await;
83 
84     let err = res.unwrap_err();
85 
86     assert!(err.is_connect() && err.is_timeout());
87 }
88 
89 #[tokio::test]
response_timeout()90 async fn response_timeout() {
91     let _ = env_logger::try_init();
92 
93     let server = server::http(move |_req| {
94         async {
95             // immediate response, but delayed body
96             let body = hyper::Body::wrap_stream(futures_util::stream::once(async {
97                 tokio::time::delay_for(Duration::from_secs(2)).await;
98                 Ok::<_, std::convert::Infallible>("Hello")
99             }));
100 
101             http::Response::new(body)
102         }
103     });
104 
105     let client = reqwest::Client::builder()
106         .timeout(Duration::from_millis(500))
107         .no_proxy()
108         .build()
109         .unwrap();
110 
111     let url = format!("http://{}/slow", server.addr());
112     let res = client.get(&url).send().await.expect("Failed to get");
113     let body = res.text().await;
114 
115     let err = body.unwrap_err();
116 
117     assert!(err.is_timeout());
118 }
119 
120 /// Tests that internal client future cancels when the oneshot channel
121 /// is canceled.
122 #[cfg(feature = "blocking")]
123 #[test]
timeout_closes_connection()124 fn timeout_closes_connection() {
125     let _ = env_logger::try_init();
126 
127     // Make Client drop *after* the Server, so the background doesn't
128     // close too early.
129     let client = reqwest::blocking::Client::builder()
130         .timeout(Duration::from_millis(500))
131         .build()
132         .unwrap();
133 
134     let server = server::http(move |_req| {
135         async {
136             // delay returning the response
137             tokio::time::delay_for(Duration::from_secs(2)).await;
138             http::Response::default()
139         }
140     });
141 
142     let url = format!("http://{}/closes", server.addr());
143     let err = client.get(&url).send().unwrap_err();
144 
145     assert!(err.is_timeout());
146     assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));
147 }
148 
149 #[cfg(feature = "blocking")]
150 #[test]
timeout_blocking_request()151 fn timeout_blocking_request() {
152     let _ = env_logger::try_init();
153 
154     // Make Client drop *after* the Server, so the background doesn't
155     // close too early.
156     let client = reqwest::blocking::Client::builder().build().unwrap();
157 
158     let server = server::http(move |_req| {
159         async {
160             // delay returning the response
161             tokio::time::delay_for(Duration::from_secs(2)).await;
162             http::Response::default()
163         }
164     });
165 
166     let url = format!("http://{}/closes", server.addr());
167     let err = client
168         .get(&url)
169         .timeout(Duration::from_millis(500))
170         .send()
171         .unwrap_err();
172 
173     assert!(err.is_timeout());
174     assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));
175 }
176 
177 #[cfg(feature = "blocking")]
178 #[test]
write_timeout_large_body()179 fn write_timeout_large_body() {
180     let _ = env_logger::try_init();
181     let body = vec![b'x'; 20_000];
182     let len = 8192;
183 
184     // Make Client drop *after* the Server, so the background doesn't
185     // close too early.
186     let client = reqwest::blocking::Client::builder()
187         .timeout(Duration::from_millis(500))
188         .build()
189         .unwrap();
190 
191     let server = server::http(move |_req| {
192         async {
193             // delay returning the response
194             tokio::time::delay_for(Duration::from_secs(2)).await;
195             http::Response::default()
196         }
197     });
198 
199     let cursor = std::io::Cursor::new(body);
200     let url = format!("http://{}/write-timeout", server.addr());
201     let err = client
202         .post(&url)
203         .body(reqwest::blocking::Body::sized(cursor, len as u64))
204         .send()
205         .unwrap_err();
206 
207     assert!(err.is_timeout());
208     assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));
209 }
210