wreq-rb 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Cargo.lock +2688 -0
- data/Cargo.toml +6 -0
- data/README.md +179 -0
- data/ext/wreq_rb/Cargo.toml +39 -0
- data/ext/wreq_rb/extconf.rb +22 -0
- data/ext/wreq_rb/src/client.rs +565 -0
- data/ext/wreq_rb/src/error.rs +25 -0
- data/ext/wreq_rb/src/lib.rs +20 -0
- data/ext/wreq_rb/src/response.rs +132 -0
- data/lib/wreq-rb/version.rb +5 -0
- data/lib/wreq-rb.rb +17 -0
- data/patches/0001-add-transfer-size-tracking.patch +292 -0
- data/vendor/wreq/Cargo.toml +306 -0
- data/vendor/wreq/LICENSE +202 -0
- data/vendor/wreq/README.md +122 -0
- data/vendor/wreq/examples/cert_store.rs +77 -0
- data/vendor/wreq/examples/connect_via_lower_priority_tokio_runtime.rs +258 -0
- data/vendor/wreq/examples/emulation.rs +118 -0
- data/vendor/wreq/examples/form.rs +14 -0
- data/vendor/wreq/examples/http1_websocket.rs +37 -0
- data/vendor/wreq/examples/http2_websocket.rs +45 -0
- data/vendor/wreq/examples/json_dynamic.rs +41 -0
- data/vendor/wreq/examples/json_typed.rs +47 -0
- data/vendor/wreq/examples/keylog.rs +16 -0
- data/vendor/wreq/examples/request_with_emulation.rs +115 -0
- data/vendor/wreq/examples/request_with_interface.rs +37 -0
- data/vendor/wreq/examples/request_with_local_address.rs +16 -0
- data/vendor/wreq/examples/request_with_proxy.rs +13 -0
- data/vendor/wreq/examples/request_with_redirect.rs +22 -0
- data/vendor/wreq/examples/request_with_version.rs +15 -0
- data/vendor/wreq/examples/tor_socks.rs +24 -0
- data/vendor/wreq/examples/unix_socket.rs +33 -0
- data/vendor/wreq/src/client/body.rs +304 -0
- data/vendor/wreq/src/client/conn/conn.rs +231 -0
- data/vendor/wreq/src/client/conn/connector.rs +549 -0
- data/vendor/wreq/src/client/conn/http.rs +1023 -0
- data/vendor/wreq/src/client/conn/proxy/socks.rs +233 -0
- data/vendor/wreq/src/client/conn/proxy/tunnel.rs +260 -0
- data/vendor/wreq/src/client/conn/proxy.rs +39 -0
- data/vendor/wreq/src/client/conn/tls_info.rs +98 -0
- data/vendor/wreq/src/client/conn/uds.rs +44 -0
- data/vendor/wreq/src/client/conn/verbose.rs +149 -0
- data/vendor/wreq/src/client/conn.rs +323 -0
- data/vendor/wreq/src/client/core/body/incoming.rs +485 -0
- data/vendor/wreq/src/client/core/body/length.rs +118 -0
- data/vendor/wreq/src/client/core/body.rs +34 -0
- data/vendor/wreq/src/client/core/common/buf.rs +149 -0
- data/vendor/wreq/src/client/core/common/rewind.rs +141 -0
- data/vendor/wreq/src/client/core/common/watch.rs +76 -0
- data/vendor/wreq/src/client/core/common.rs +3 -0
- data/vendor/wreq/src/client/core/conn/http1.rs +342 -0
- data/vendor/wreq/src/client/core/conn/http2.rs +307 -0
- data/vendor/wreq/src/client/core/conn.rs +11 -0
- data/vendor/wreq/src/client/core/dispatch.rs +299 -0
- data/vendor/wreq/src/client/core/error.rs +435 -0
- data/vendor/wreq/src/client/core/ext.rs +201 -0
- data/vendor/wreq/src/client/core/http1.rs +178 -0
- data/vendor/wreq/src/client/core/http2.rs +483 -0
- data/vendor/wreq/src/client/core/proto/h1/conn.rs +988 -0
- data/vendor/wreq/src/client/core/proto/h1/decode.rs +1170 -0
- data/vendor/wreq/src/client/core/proto/h1/dispatch.rs +684 -0
- data/vendor/wreq/src/client/core/proto/h1/encode.rs +580 -0
- data/vendor/wreq/src/client/core/proto/h1/io.rs +879 -0
- data/vendor/wreq/src/client/core/proto/h1/role.rs +694 -0
- data/vendor/wreq/src/client/core/proto/h1.rs +104 -0
- data/vendor/wreq/src/client/core/proto/h2/client.rs +650 -0
- data/vendor/wreq/src/client/core/proto/h2/ping.rs +539 -0
- data/vendor/wreq/src/client/core/proto/h2.rs +379 -0
- data/vendor/wreq/src/client/core/proto/headers.rs +138 -0
- data/vendor/wreq/src/client/core/proto.rs +58 -0
- data/vendor/wreq/src/client/core/rt/bounds.rs +57 -0
- data/vendor/wreq/src/client/core/rt/timer.rs +150 -0
- data/vendor/wreq/src/client/core/rt/tokio.rs +99 -0
- data/vendor/wreq/src/client/core/rt.rs +25 -0
- data/vendor/wreq/src/client/core/upgrade.rs +267 -0
- data/vendor/wreq/src/client/core.rs +16 -0
- data/vendor/wreq/src/client/emulation.rs +161 -0
- data/vendor/wreq/src/client/http/client/error.rs +142 -0
- data/vendor/wreq/src/client/http/client/exec.rs +29 -0
- data/vendor/wreq/src/client/http/client/extra.rs +77 -0
- data/vendor/wreq/src/client/http/client/lazy.rs +79 -0
- data/vendor/wreq/src/client/http/client/pool.rs +1105 -0
- data/vendor/wreq/src/client/http/client/util.rs +104 -0
- data/vendor/wreq/src/client/http/client.rs +1003 -0
- data/vendor/wreq/src/client/http/future.rs +99 -0
- data/vendor/wreq/src/client/http.rs +1629 -0
- data/vendor/wreq/src/client/layer/config/options.rs +156 -0
- data/vendor/wreq/src/client/layer/config.rs +116 -0
- data/vendor/wreq/src/client/layer/cookie.rs +161 -0
- data/vendor/wreq/src/client/layer/decoder.rs +139 -0
- data/vendor/wreq/src/client/layer/redirect/future.rs +270 -0
- data/vendor/wreq/src/client/layer/redirect/policy.rs +63 -0
- data/vendor/wreq/src/client/layer/redirect.rs +145 -0
- data/vendor/wreq/src/client/layer/retry/classify.rs +105 -0
- data/vendor/wreq/src/client/layer/retry/scope.rs +51 -0
- data/vendor/wreq/src/client/layer/retry.rs +151 -0
- data/vendor/wreq/src/client/layer/timeout/body.rs +233 -0
- data/vendor/wreq/src/client/layer/timeout/future.rs +90 -0
- data/vendor/wreq/src/client/layer/timeout.rs +177 -0
- data/vendor/wreq/src/client/layer.rs +15 -0
- data/vendor/wreq/src/client/multipart.rs +717 -0
- data/vendor/wreq/src/client/request.rs +818 -0
- data/vendor/wreq/src/client/response.rs +534 -0
- data/vendor/wreq/src/client/ws/json.rs +99 -0
- data/vendor/wreq/src/client/ws/message.rs +453 -0
- data/vendor/wreq/src/client/ws.rs +714 -0
- data/vendor/wreq/src/client.rs +27 -0
- data/vendor/wreq/src/config.rs +140 -0
- data/vendor/wreq/src/cookie.rs +579 -0
- data/vendor/wreq/src/dns/gai.rs +249 -0
- data/vendor/wreq/src/dns/hickory.rs +78 -0
- data/vendor/wreq/src/dns/resolve.rs +180 -0
- data/vendor/wreq/src/dns.rs +69 -0
- data/vendor/wreq/src/error.rs +502 -0
- data/vendor/wreq/src/ext.rs +398 -0
- data/vendor/wreq/src/hash.rs +143 -0
- data/vendor/wreq/src/header.rs +506 -0
- data/vendor/wreq/src/into_uri.rs +187 -0
- data/vendor/wreq/src/lib.rs +586 -0
- data/vendor/wreq/src/proxy/mac.rs +82 -0
- data/vendor/wreq/src/proxy/matcher.rs +806 -0
- data/vendor/wreq/src/proxy/uds.rs +66 -0
- data/vendor/wreq/src/proxy/win.rs +31 -0
- data/vendor/wreq/src/proxy.rs +569 -0
- data/vendor/wreq/src/redirect.rs +575 -0
- data/vendor/wreq/src/retry.rs +198 -0
- data/vendor/wreq/src/sync.rs +129 -0
- data/vendor/wreq/src/tls/conn/cache.rs +123 -0
- data/vendor/wreq/src/tls/conn/cert_compression.rs +125 -0
- data/vendor/wreq/src/tls/conn/ext.rs +82 -0
- data/vendor/wreq/src/tls/conn/macros.rs +34 -0
- data/vendor/wreq/src/tls/conn/service.rs +138 -0
- data/vendor/wreq/src/tls/conn.rs +681 -0
- data/vendor/wreq/src/tls/keylog/handle.rs +64 -0
- data/vendor/wreq/src/tls/keylog.rs +99 -0
- data/vendor/wreq/src/tls/options.rs +464 -0
- data/vendor/wreq/src/tls/x509/identity.rs +122 -0
- data/vendor/wreq/src/tls/x509/parser.rs +71 -0
- data/vendor/wreq/src/tls/x509/store.rs +228 -0
- data/vendor/wreq/src/tls/x509.rs +68 -0
- data/vendor/wreq/src/tls.rs +154 -0
- data/vendor/wreq/src/trace.rs +55 -0
- data/vendor/wreq/src/util.rs +122 -0
- data/vendor/wreq/tests/badssl.rs +228 -0
- data/vendor/wreq/tests/brotli.rs +350 -0
- data/vendor/wreq/tests/client.rs +1098 -0
- data/vendor/wreq/tests/connector_layers.rs +227 -0
- data/vendor/wreq/tests/cookie.rs +306 -0
- data/vendor/wreq/tests/deflate.rs +347 -0
- data/vendor/wreq/tests/emulation.rs +260 -0
- data/vendor/wreq/tests/gzip.rs +347 -0
- data/vendor/wreq/tests/layers.rs +261 -0
- data/vendor/wreq/tests/multipart.rs +165 -0
- data/vendor/wreq/tests/proxy.rs +438 -0
- data/vendor/wreq/tests/redirect.rs +629 -0
- data/vendor/wreq/tests/retry.rs +135 -0
- data/vendor/wreq/tests/support/delay_server.rs +117 -0
- data/vendor/wreq/tests/support/error.rs +16 -0
- data/vendor/wreq/tests/support/layer.rs +183 -0
- data/vendor/wreq/tests/support/mod.rs +9 -0
- data/vendor/wreq/tests/support/server.rs +232 -0
- data/vendor/wreq/tests/timeouts.rs +281 -0
- data/vendor/wreq/tests/unix_socket.rs +135 -0
- data/vendor/wreq/tests/upgrade.rs +98 -0
- data/vendor/wreq/tests/zstd.rs +559 -0
- metadata +225 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
mod support;
|
|
2
|
+
use std::time::Duration;
|
|
3
|
+
|
|
4
|
+
use pretty_env_logger::env_logger;
|
|
5
|
+
use support::server;
|
|
6
|
+
use wreq::Client;
|
|
7
|
+
|
|
8
|
+
#[tokio::test]
|
|
9
|
+
async fn client_timeout() {
|
|
10
|
+
let _ = env_logger::try_init();
|
|
11
|
+
|
|
12
|
+
let server = server::http(move |_req| {
|
|
13
|
+
async {
|
|
14
|
+
// delay returning the response
|
|
15
|
+
tokio::time::sleep(Duration::from_millis(300)).await;
|
|
16
|
+
http::Response::default()
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
let client = Client::builder()
|
|
21
|
+
.timeout(Duration::from_millis(100))
|
|
22
|
+
.no_proxy()
|
|
23
|
+
.build()
|
|
24
|
+
.unwrap();
|
|
25
|
+
|
|
26
|
+
let url = format!("http://{}/slow", server.addr());
|
|
27
|
+
let err = client.get(&url).send().await.unwrap_err();
|
|
28
|
+
|
|
29
|
+
assert!(err.is_timeout());
|
|
30
|
+
assert_eq!(err.uri().map(|u| u.to_string()), Some(url));
|
|
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::sleep(Duration::from_millis(300)).await;
|
|
41
|
+
http::Response::default()
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
let client = Client::builder().no_proxy().build().unwrap();
|
|
46
|
+
|
|
47
|
+
let url = format!("http://{}/slow", server.addr());
|
|
48
|
+
|
|
49
|
+
let err = client
|
|
50
|
+
.get(&url)
|
|
51
|
+
.timeout(Duration::from_millis(100))
|
|
52
|
+
.send()
|
|
53
|
+
.await
|
|
54
|
+
.unwrap_err();
|
|
55
|
+
|
|
56
|
+
assert!(err.is_timeout() && !err.is_connect());
|
|
57
|
+
assert_eq!(err.uri().map(|u| u.to_string()), Some(url));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
#[tokio::test]
|
|
61
|
+
async fn connect_timeout() {
|
|
62
|
+
let _ = env_logger::try_init();
|
|
63
|
+
|
|
64
|
+
let client = Client::builder()
|
|
65
|
+
.connect_timeout(Duration::from_millis(100))
|
|
66
|
+
.no_proxy()
|
|
67
|
+
.build()
|
|
68
|
+
.unwrap();
|
|
69
|
+
|
|
70
|
+
let url = "http://192.0.2.1:81/slow";
|
|
71
|
+
|
|
72
|
+
let err = client
|
|
73
|
+
.get(url)
|
|
74
|
+
.timeout(Duration::from_millis(1000))
|
|
75
|
+
.send()
|
|
76
|
+
.await
|
|
77
|
+
.unwrap_err();
|
|
78
|
+
|
|
79
|
+
assert!(err.is_timeout());
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#[tokio::test]
|
|
83
|
+
async fn connect_many_timeout_succeeds() {
|
|
84
|
+
let _ = env_logger::try_init();
|
|
85
|
+
|
|
86
|
+
let server = server::http(move |_req| async { http::Response::default() });
|
|
87
|
+
let port = server.addr().port();
|
|
88
|
+
|
|
89
|
+
let client = Client::builder()
|
|
90
|
+
.resolve_to_addrs(
|
|
91
|
+
"many_addrs",
|
|
92
|
+
["127.0.0.1:81".parse().unwrap(), server.addr()],
|
|
93
|
+
)
|
|
94
|
+
.connect_timeout(Duration::from_millis(100))
|
|
95
|
+
.no_proxy()
|
|
96
|
+
.build()
|
|
97
|
+
.unwrap();
|
|
98
|
+
|
|
99
|
+
let url = format!("http://many_addrs:{port}/eventual");
|
|
100
|
+
|
|
101
|
+
let _ = client
|
|
102
|
+
.get(url)
|
|
103
|
+
.timeout(Duration::from_millis(1000))
|
|
104
|
+
.send()
|
|
105
|
+
.await
|
|
106
|
+
.unwrap();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
#[tokio::test]
|
|
110
|
+
async fn connect_many_timeout() {
|
|
111
|
+
let _ = env_logger::try_init();
|
|
112
|
+
|
|
113
|
+
let client = Client::builder()
|
|
114
|
+
.resolve_to_addrs(
|
|
115
|
+
"many_addrs",
|
|
116
|
+
[
|
|
117
|
+
"192.0.2.1:81".parse().unwrap(),
|
|
118
|
+
"192.0.2.2:81".parse().unwrap(),
|
|
119
|
+
],
|
|
120
|
+
)
|
|
121
|
+
.connect_timeout(Duration::from_millis(100))
|
|
122
|
+
.no_proxy()
|
|
123
|
+
.build()
|
|
124
|
+
.unwrap();
|
|
125
|
+
|
|
126
|
+
let url = "http://many_addrs:81/slow".to_string();
|
|
127
|
+
|
|
128
|
+
let err = client
|
|
129
|
+
.get(url)
|
|
130
|
+
.timeout(Duration::from_millis(1000))
|
|
131
|
+
.send()
|
|
132
|
+
.await
|
|
133
|
+
.unwrap_err();
|
|
134
|
+
|
|
135
|
+
assert!(err.is_connect() && err.is_timeout());
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
#[cfg(feature = "stream")]
|
|
139
|
+
#[tokio::test]
|
|
140
|
+
async fn response_timeout() {
|
|
141
|
+
let _ = env_logger::try_init();
|
|
142
|
+
|
|
143
|
+
let server = server::http(move |_req| {
|
|
144
|
+
async {
|
|
145
|
+
// immediate response, but delayed body
|
|
146
|
+
let body = wreq::Body::wrap_stream(futures_util::stream::once(async {
|
|
147
|
+
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
148
|
+
Ok::<_, std::convert::Infallible>("Hello")
|
|
149
|
+
}));
|
|
150
|
+
|
|
151
|
+
http::Response::new(body)
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
let client = Client::builder()
|
|
156
|
+
.timeout(Duration::from_millis(500))
|
|
157
|
+
.no_proxy()
|
|
158
|
+
.build()
|
|
159
|
+
.unwrap();
|
|
160
|
+
|
|
161
|
+
let url = format!("http://{}/slow", server.addr());
|
|
162
|
+
let res = client.get(&url).send().await.expect("Failed to get");
|
|
163
|
+
let err = res.text().await.unwrap_err();
|
|
164
|
+
|
|
165
|
+
assert!(err.is_timeout());
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
#[tokio::test]
|
|
169
|
+
async fn read_timeout_applies_to_headers() {
|
|
170
|
+
let _ = env_logger::try_init();
|
|
171
|
+
|
|
172
|
+
let server = server::http(move |_req| {
|
|
173
|
+
async {
|
|
174
|
+
// delay returning the response
|
|
175
|
+
tokio::time::sleep(Duration::from_millis(300)).await;
|
|
176
|
+
http::Response::default()
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
let client = Client::builder()
|
|
181
|
+
.read_timeout(Duration::from_millis(100))
|
|
182
|
+
.no_proxy()
|
|
183
|
+
.build()
|
|
184
|
+
.unwrap();
|
|
185
|
+
|
|
186
|
+
let url = format!("http://{}/slow", server.addr());
|
|
187
|
+
|
|
188
|
+
let err = client.get(&url).send().await.unwrap_err();
|
|
189
|
+
|
|
190
|
+
assert!(err.is_timeout());
|
|
191
|
+
assert_eq!(err.uri().map(|u| u.to_string()), Some(url));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
#[cfg(feature = "stream")]
|
|
195
|
+
#[tokio::test]
|
|
196
|
+
async fn read_timeout_applies_to_body() {
|
|
197
|
+
let _ = env_logger::try_init();
|
|
198
|
+
|
|
199
|
+
let server = server::http(move |_req| {
|
|
200
|
+
async {
|
|
201
|
+
// immediate response, but delayed body
|
|
202
|
+
let body = wreq::Body::wrap_stream(futures_util::stream::once(async {
|
|
203
|
+
tokio::time::sleep(Duration::from_millis(300)).await;
|
|
204
|
+
Ok::<_, std::convert::Infallible>("Hello")
|
|
205
|
+
}));
|
|
206
|
+
|
|
207
|
+
http::Response::new(body)
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
let client = Client::builder()
|
|
212
|
+
.read_timeout(Duration::from_millis(100))
|
|
213
|
+
.no_proxy()
|
|
214
|
+
.build()
|
|
215
|
+
.unwrap();
|
|
216
|
+
|
|
217
|
+
let url = format!("http://{}/slow", server.addr());
|
|
218
|
+
let res = client.get(&url).send().await.expect("Failed to get");
|
|
219
|
+
let err = res.text().await.unwrap_err();
|
|
220
|
+
|
|
221
|
+
assert!(err.is_timeout());
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
#[cfg(feature = "stream")]
|
|
225
|
+
#[tokio::test]
|
|
226
|
+
async fn read_timeout_allows_slow_response_body() {
|
|
227
|
+
let _ = env_logger::try_init();
|
|
228
|
+
|
|
229
|
+
let server = server::http(move |_req| {
|
|
230
|
+
async {
|
|
231
|
+
// immediate response, but body that has slow chunks
|
|
232
|
+
let slow = futures_util::stream::unfold(0, |state| async move {
|
|
233
|
+
if state < 3 {
|
|
234
|
+
tokio::time::sleep(Duration::from_millis(100)).await;
|
|
235
|
+
Some((
|
|
236
|
+
Ok::<_, std::convert::Infallible>(state.to_string()),
|
|
237
|
+
state + 1,
|
|
238
|
+
))
|
|
239
|
+
} else {
|
|
240
|
+
None
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
let body = wreq::Body::wrap_stream(slow);
|
|
244
|
+
|
|
245
|
+
http::Response::new(body)
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
let client = Client::builder()
|
|
250
|
+
.read_timeout(Duration::from_millis(200))
|
|
251
|
+
//.timeout(Duration::from_millis(200))
|
|
252
|
+
.no_proxy()
|
|
253
|
+
.build()
|
|
254
|
+
.unwrap();
|
|
255
|
+
|
|
256
|
+
let url = format!("http://{}/slow", server.addr());
|
|
257
|
+
let res = client.get(&url).send().await.expect("Failed to get");
|
|
258
|
+
let body = res.text().await.expect("body text");
|
|
259
|
+
|
|
260
|
+
assert_eq!(body, "012");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
#[tokio::test]
|
|
264
|
+
async fn response_body_timeout_forwards_size_hint() {
|
|
265
|
+
let _ = env_logger::try_init();
|
|
266
|
+
|
|
267
|
+
let server = server::http(move |_req| async { http::Response::new(b"hello".to_vec().into()) });
|
|
268
|
+
|
|
269
|
+
let client = Client::builder().no_proxy().build().unwrap();
|
|
270
|
+
|
|
271
|
+
let url = format!("http://{}/slow", server.addr());
|
|
272
|
+
|
|
273
|
+
let res = client
|
|
274
|
+
.get(&url)
|
|
275
|
+
.timeout(Duration::from_secs(1))
|
|
276
|
+
.send()
|
|
277
|
+
.await
|
|
278
|
+
.expect("response");
|
|
279
|
+
|
|
280
|
+
assert_eq!(res.content_length(), Some(5));
|
|
281
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#![cfg(unix)]
|
|
2
|
+
|
|
3
|
+
use std::{hash::BuildHasher, time::Duration};
|
|
4
|
+
|
|
5
|
+
use http::Method;
|
|
6
|
+
use http_body_util::Full;
|
|
7
|
+
use hyper::{Request, Response, body::Incoming, service::service_fn};
|
|
8
|
+
use hyper_util::{
|
|
9
|
+
rt::{TokioExecutor, TokioIo},
|
|
10
|
+
server::conn::auto::Builder,
|
|
11
|
+
};
|
|
12
|
+
use tokio::{net::UnixListener, task};
|
|
13
|
+
use wreq::{Client, Proxy};
|
|
14
|
+
|
|
15
|
+
fn random_sock_path() -> std::path::PathBuf {
|
|
16
|
+
let mut buf = std::env::temp_dir();
|
|
17
|
+
// libstd uses system random to create each one
|
|
18
|
+
let rng = std::collections::hash_map::RandomState::new();
|
|
19
|
+
let n = rng.hash_one("uds-sock");
|
|
20
|
+
buf.push(format!("test-uds-sock-{}", n));
|
|
21
|
+
buf
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#[tokio::test]
|
|
25
|
+
async fn test_unix_socket() {
|
|
26
|
+
let sock_path = random_sock_path();
|
|
27
|
+
|
|
28
|
+
let listener = UnixListener::bind(&sock_path).unwrap();
|
|
29
|
+
let server = async move {
|
|
30
|
+
loop {
|
|
31
|
+
let (stream, _) = listener.accept().await.unwrap();
|
|
32
|
+
let io = TokioIo::new(stream);
|
|
33
|
+
let service = service_fn(|_req: Request<Incoming>| async {
|
|
34
|
+
Ok::<_, hyper::Error>(Response::new(Full::new(&b"hello unix"[..])))
|
|
35
|
+
});
|
|
36
|
+
task::spawn(async move {
|
|
37
|
+
if let Err(e) = hyper::server::conn::http1::Builder::new()
|
|
38
|
+
.serve_connection(io, service)
|
|
39
|
+
.await
|
|
40
|
+
{
|
|
41
|
+
eprintln!("server error: {:?}", e);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
tokio::spawn(server);
|
|
47
|
+
|
|
48
|
+
let client = Client::builder()
|
|
49
|
+
.proxy(Proxy::unix(sock_path).unwrap())
|
|
50
|
+
.timeout(Duration::from_secs(10))
|
|
51
|
+
.build()
|
|
52
|
+
.unwrap();
|
|
53
|
+
|
|
54
|
+
let resp = client.get("http://localhost/").send().await.unwrap();
|
|
55
|
+
let body = resp.text().await.unwrap();
|
|
56
|
+
assert_eq!(body, "hello unix");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
#[tokio::test]
|
|
60
|
+
async fn test_proxy_unix_socket() {
|
|
61
|
+
let sock_path = random_sock_path();
|
|
62
|
+
|
|
63
|
+
let listener = UnixListener::bind(&sock_path).unwrap();
|
|
64
|
+
let server = async move {
|
|
65
|
+
loop {
|
|
66
|
+
let (stream, _) = listener.accept().await.unwrap();
|
|
67
|
+
let io = TokioIo::new(stream);
|
|
68
|
+
let service = service_fn(|req: Request<Incoming>| {
|
|
69
|
+
async move {
|
|
70
|
+
if Method::CONNECT == req.method() {
|
|
71
|
+
// Received an HTTP request like:
|
|
72
|
+
// ```
|
|
73
|
+
// CONNECT www.domain.com:443 HTTP/1.1
|
|
74
|
+
// Host: www.domain.com:443
|
|
75
|
+
// Proxy-Connection: Keep-Alive
|
|
76
|
+
// ```
|
|
77
|
+
//
|
|
78
|
+
// When HTTP method is CONNECT we should return an empty body,
|
|
79
|
+
// then we can eventually upgrade the connection and talk a new protocol.
|
|
80
|
+
//
|
|
81
|
+
// Note: only after client received an empty body with STATUS_OK can the
|
|
82
|
+
// connection be upgraded, so we can't return a response inside
|
|
83
|
+
// `on_upgrade` future.
|
|
84
|
+
let authority = req.uri().authority().cloned().unwrap();
|
|
85
|
+
tokio::task::spawn({
|
|
86
|
+
let req = req;
|
|
87
|
+
async move {
|
|
88
|
+
match hyper::upgrade::on(req).await {
|
|
89
|
+
Ok(upgraded) => {
|
|
90
|
+
tracing::info!("upgraded connection to: {}", authority);
|
|
91
|
+
if let Ok(mut io) =
|
|
92
|
+
tokio::net::TcpStream::connect(authority.to_string())
|
|
93
|
+
.await
|
|
94
|
+
{
|
|
95
|
+
let _ = tokio::io::copy_bidirectional(
|
|
96
|
+
&mut TokioIo::new(upgraded),
|
|
97
|
+
&mut io,
|
|
98
|
+
)
|
|
99
|
+
.await;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
Err(e) => tracing::warn!("upgrade error: {}", e),
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
Ok::<_, hyper::Error>(Response::new(Full::new(&b""[..])))
|
|
108
|
+
} else {
|
|
109
|
+
Ok::<_, hyper::Error>(Response::new(Full::new(
|
|
110
|
+
&b"unsupported request method"[..],
|
|
111
|
+
)))
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
task::spawn(async move {
|
|
116
|
+
if let Err(e) = Builder::new(TokioExecutor::new())
|
|
117
|
+
.serve_connection_with_upgrades(io, service)
|
|
118
|
+
.await
|
|
119
|
+
{
|
|
120
|
+
eprintln!("server error: {:?}", e);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
tokio::spawn(server);
|
|
126
|
+
|
|
127
|
+
let client = Client::builder()
|
|
128
|
+
.proxy(Proxy::unix(sock_path).unwrap())
|
|
129
|
+
.timeout(Duration::from_secs(10))
|
|
130
|
+
.build()
|
|
131
|
+
.unwrap();
|
|
132
|
+
|
|
133
|
+
let resp = client.get("https://www.google.com").send().await.unwrap();
|
|
134
|
+
assert!(resp.status().is_success(), "Expected successful response");
|
|
135
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
mod support;
|
|
2
|
+
use http::Method;
|
|
3
|
+
use support::server;
|
|
4
|
+
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
|
5
|
+
use wreq::Client;
|
|
6
|
+
|
|
7
|
+
#[tokio::test]
|
|
8
|
+
async fn http_upgrade() {
|
|
9
|
+
let server = server::http(move |req| {
|
|
10
|
+
assert_eq!(req.method(), "GET");
|
|
11
|
+
assert_eq!(req.headers()["connection"], "upgrade");
|
|
12
|
+
assert_eq!(req.headers()["upgrade"], "foobar");
|
|
13
|
+
|
|
14
|
+
tokio::spawn(async move {
|
|
15
|
+
let mut upgraded = hyper_util::rt::TokioIo::new(hyper::upgrade::on(req).await.unwrap());
|
|
16
|
+
|
|
17
|
+
let mut buf = vec![0; 7];
|
|
18
|
+
upgraded.read_exact(&mut buf).await.unwrap();
|
|
19
|
+
assert_eq!(buf, b"foo=bar");
|
|
20
|
+
|
|
21
|
+
upgraded.write_all(b"bar=foo").await.unwrap();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
async {
|
|
25
|
+
http::Response::builder()
|
|
26
|
+
.status(http::StatusCode::SWITCHING_PROTOCOLS)
|
|
27
|
+
.header(http::header::CONNECTION, "upgrade")
|
|
28
|
+
.header(http::header::UPGRADE, "foobar")
|
|
29
|
+
.body(wreq::Body::default())
|
|
30
|
+
.unwrap()
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
let res = Client::builder()
|
|
35
|
+
.build()
|
|
36
|
+
.unwrap()
|
|
37
|
+
.get(format!("http://{}", server.addr()))
|
|
38
|
+
.header(http::header::CONNECTION, "upgrade")
|
|
39
|
+
.header(http::header::UPGRADE, "foobar")
|
|
40
|
+
.send()
|
|
41
|
+
.await
|
|
42
|
+
.unwrap();
|
|
43
|
+
|
|
44
|
+
assert_eq!(res.status(), http::StatusCode::SWITCHING_PROTOCOLS);
|
|
45
|
+
let mut upgraded = res.upgrade().await.unwrap();
|
|
46
|
+
|
|
47
|
+
upgraded.write_all(b"foo=bar").await.unwrap();
|
|
48
|
+
|
|
49
|
+
let mut buf = vec![];
|
|
50
|
+
upgraded.read_to_end(&mut buf).await.unwrap();
|
|
51
|
+
assert_eq!(buf, b"bar=foo");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
#[tokio::test]
|
|
55
|
+
async fn http2_upgrade() {
|
|
56
|
+
let server = server::http_with_config(
|
|
57
|
+
move |req| {
|
|
58
|
+
assert_eq!(req.method(), http::Method::CONNECT);
|
|
59
|
+
assert_eq!(req.version(), http::Version::HTTP_2);
|
|
60
|
+
|
|
61
|
+
tokio::spawn(async move {
|
|
62
|
+
let mut upgraded =
|
|
63
|
+
hyper_util::rt::TokioIo::new(hyper::upgrade::on(req).await.unwrap());
|
|
64
|
+
|
|
65
|
+
let mut buf = vec![0; 7];
|
|
66
|
+
upgraded.read_exact(&mut buf).await.unwrap();
|
|
67
|
+
assert_eq!(buf, b"foo=bar");
|
|
68
|
+
|
|
69
|
+
upgraded.write_all(b"bar=foo").await.unwrap();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
async { Ok::<_, std::convert::Infallible>(http::Response::default()) }
|
|
73
|
+
},
|
|
74
|
+
|builder| {
|
|
75
|
+
let mut http2 = builder.http2();
|
|
76
|
+
http2.enable_connect_protocol();
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
let res = Client::builder()
|
|
81
|
+
.http2_only()
|
|
82
|
+
.build()
|
|
83
|
+
.unwrap()
|
|
84
|
+
.request(Method::CONNECT, format!("http://{}", server.addr()))
|
|
85
|
+
.send()
|
|
86
|
+
.await
|
|
87
|
+
.unwrap();
|
|
88
|
+
|
|
89
|
+
assert_eq!(res.status(), http::StatusCode::OK);
|
|
90
|
+
assert_eq!(res.version(), http::Version::HTTP_2);
|
|
91
|
+
let mut upgraded = res.upgrade().await.unwrap();
|
|
92
|
+
|
|
93
|
+
upgraded.write_all(b"foo=bar").await.unwrap();
|
|
94
|
+
|
|
95
|
+
let mut buf = vec![];
|
|
96
|
+
upgraded.read_to_end(&mut buf).await.unwrap();
|
|
97
|
+
assert_eq!(buf, b"bar=foo");
|
|
98
|
+
}
|