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