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