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,150 @@
|
|
|
1
|
+
//! Provides a timer trait with timer-like functions
|
|
2
|
+
|
|
3
|
+
use std::{
|
|
4
|
+
any::TypeId,
|
|
5
|
+
future::Future,
|
|
6
|
+
pin::Pin,
|
|
7
|
+
sync::Arc,
|
|
8
|
+
time::{Duration, Instant},
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/// A timer which provides timer-like functions.
|
|
12
|
+
pub trait Timer {
|
|
13
|
+
/// Return a future that resolves in `duration` time.
|
|
14
|
+
fn sleep(&self, duration: Duration) -> Pin<Box<dyn Sleep>>;
|
|
15
|
+
|
|
16
|
+
/// Return a future that resolves at `deadline`.
|
|
17
|
+
fn sleep_until(&self, deadline: Instant) -> Pin<Box<dyn Sleep>>;
|
|
18
|
+
|
|
19
|
+
/// Return an `Instant` representing the current time.
|
|
20
|
+
///
|
|
21
|
+
/// The default implementation returns [`Instant::now()`].
|
|
22
|
+
fn now(&self) -> Instant {
|
|
23
|
+
Instant::now()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/// Reset a future to resolve at `new_deadline` instead.
|
|
27
|
+
fn reset(&self, sleep: &mut Pin<Box<dyn Sleep>>, new_deadline: Instant) {
|
|
28
|
+
*sleep = self.sleep_until(new_deadline);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/// A future returned by a `Timer`.
|
|
33
|
+
pub trait Sleep: Send + Sync + Future<Output = ()> {
|
|
34
|
+
#[doc(hidden)]
|
|
35
|
+
/// This method is private and can not be implemented by downstream crate
|
|
36
|
+
fn __type_id(&self, _: private::Sealed) -> TypeId
|
|
37
|
+
where
|
|
38
|
+
Self: 'static,
|
|
39
|
+
{
|
|
40
|
+
TypeId::of::<Self>()
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// A handle to a shared timer instance.
|
|
45
|
+
///
|
|
46
|
+
/// `TimerHandle` provides a reference-counted, thread-safe handle to any type implementing the
|
|
47
|
+
/// [`Timer`] trait. It allows cloning and sharing a timer implementation across multiple components
|
|
48
|
+
/// or tasks.
|
|
49
|
+
///
|
|
50
|
+
/// This is typically used to abstract over different timer backends and to provide a unified
|
|
51
|
+
/// interface for spawning sleep futures or scheduling timeouts.
|
|
52
|
+
#[derive(Clone)]
|
|
53
|
+
pub struct ArcTimer(Arc<dyn Timer + Send + Sync>);
|
|
54
|
+
|
|
55
|
+
/// A user-provided timer to time background tasks.
|
|
56
|
+
#[derive(Clone)]
|
|
57
|
+
pub enum Time {
|
|
58
|
+
Timer(ArcTimer),
|
|
59
|
+
Empty,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// =====impl Sleep =====
|
|
63
|
+
|
|
64
|
+
impl dyn Sleep {
|
|
65
|
+
//! This is a re-implementation of downcast methods from std::any::Any
|
|
66
|
+
|
|
67
|
+
/// Check whether the type is the same as `T`
|
|
68
|
+
pub fn is<T>(&self) -> bool
|
|
69
|
+
where
|
|
70
|
+
T: Sleep + 'static,
|
|
71
|
+
{
|
|
72
|
+
self.__type_id(private::Sealed {}) == TypeId::of::<T>()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// Downcast a pinned &mut Sleep object to its original type
|
|
76
|
+
pub fn downcast_mut_pin<T>(self: Pin<&mut Self>) -> Option<Pin<&mut T>>
|
|
77
|
+
where
|
|
78
|
+
T: Sleep + 'static,
|
|
79
|
+
{
|
|
80
|
+
if self.is::<T>() {
|
|
81
|
+
#[allow(unsafe_code)]
|
|
82
|
+
unsafe {
|
|
83
|
+
let inner = Pin::into_inner_unchecked(self);
|
|
84
|
+
Some(Pin::new_unchecked(
|
|
85
|
+
&mut *(&mut *inner as *mut dyn Sleep as *mut T),
|
|
86
|
+
))
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
None
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// =====impl ArcTimer =====
|
|
95
|
+
|
|
96
|
+
impl ArcTimer {
|
|
97
|
+
pub(crate) fn new<T>(inner: T) -> Self
|
|
98
|
+
where
|
|
99
|
+
T: Timer + Send + Sync + 'static,
|
|
100
|
+
{
|
|
101
|
+
Self(Arc::new(inner))
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
impl Timer for ArcTimer {
|
|
106
|
+
fn sleep(&self, duration: Duration) -> Pin<Box<dyn Sleep>> {
|
|
107
|
+
self.0.sleep(duration)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
fn now(&self) -> Instant {
|
|
111
|
+
tokio::time::Instant::now().into()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
fn sleep_until(&self, deadline: Instant) -> Pin<Box<dyn Sleep>> {
|
|
115
|
+
self.0.sleep_until(deadline)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// =====impl Time =====
|
|
120
|
+
|
|
121
|
+
impl Time {
|
|
122
|
+
pub(crate) fn sleep(&self, duration: Duration) -> Pin<Box<dyn Sleep>> {
|
|
123
|
+
match *self {
|
|
124
|
+
Time::Empty => {
|
|
125
|
+
panic!("You must supply a timer.")
|
|
126
|
+
}
|
|
127
|
+
Time::Timer(ref t) => t.sleep(duration),
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
pub(crate) fn now(&self) -> Instant {
|
|
132
|
+
match *self {
|
|
133
|
+
Time::Empty => Instant::now(),
|
|
134
|
+
Time::Timer(ref t) => t.now(),
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
pub(crate) fn reset(&self, sleep: &mut Pin<Box<dyn Sleep>>, new_deadline: Instant) {
|
|
139
|
+
match *self {
|
|
140
|
+
Time::Empty => {
|
|
141
|
+
panic!("You must supply a timer.")
|
|
142
|
+
}
|
|
143
|
+
Time::Timer(ref t) => t.reset(sleep, new_deadline),
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
mod private {
|
|
149
|
+
pub struct Sealed {}
|
|
150
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
//! Tokio IO integration for core.
|
|
2
|
+
use std::{
|
|
3
|
+
future::Future,
|
|
4
|
+
pin::Pin,
|
|
5
|
+
task::{Context, Poll},
|
|
6
|
+
time::{Duration, Instant},
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
use pin_project_lite::pin_project;
|
|
10
|
+
|
|
11
|
+
use super::{Executor, Sleep, Timer};
|
|
12
|
+
|
|
13
|
+
/// Future executor that utilises `tokio` threads.
|
|
14
|
+
#[non_exhaustive]
|
|
15
|
+
#[derive(Default, Debug, Clone)]
|
|
16
|
+
pub struct TokioExecutor {}
|
|
17
|
+
|
|
18
|
+
/// A Timer that uses the tokio runtime.
|
|
19
|
+
#[non_exhaustive]
|
|
20
|
+
#[derive(Default, Clone, Debug)]
|
|
21
|
+
pub struct TokioTimer;
|
|
22
|
+
|
|
23
|
+
// Use TokioSleep to get tokio::time::Sleep to implement Unpin.
|
|
24
|
+
// see https://docs.rs/tokio/latest/tokio/time/struct.Sleep.html
|
|
25
|
+
pin_project! {
|
|
26
|
+
#[derive(Debug)]
|
|
27
|
+
struct TokioSleep {
|
|
28
|
+
#[pin]
|
|
29
|
+
inner: tokio::time::Sleep,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ===== impl TokioExecutor =====
|
|
34
|
+
|
|
35
|
+
impl<Fut> Executor<Fut> for TokioExecutor
|
|
36
|
+
where
|
|
37
|
+
Fut: Future + Send + 'static,
|
|
38
|
+
Fut::Output: Send + 'static,
|
|
39
|
+
{
|
|
40
|
+
fn execute(&self, fut: Fut) {
|
|
41
|
+
tokio::spawn(fut);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
impl TokioExecutor {
|
|
46
|
+
/// Create new executor that relies on [`tokio::spawn`] to execute futures.
|
|
47
|
+
pub fn new() -> Self {
|
|
48
|
+
Self {}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ==== impl TokioTimer =====
|
|
53
|
+
|
|
54
|
+
impl Timer for TokioTimer {
|
|
55
|
+
fn sleep(&self, duration: Duration) -> Pin<Box<dyn Sleep>> {
|
|
56
|
+
Box::pin(TokioSleep {
|
|
57
|
+
inner: tokio::time::sleep(duration),
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fn sleep_until(&self, deadline: Instant) -> Pin<Box<dyn Sleep>> {
|
|
62
|
+
Box::pin(TokioSleep {
|
|
63
|
+
inner: tokio::time::sleep_until(deadline.into()),
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
fn now(&self) -> Instant {
|
|
68
|
+
tokio::time::Instant::now().into()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
fn reset(&self, sleep: &mut Pin<Box<dyn Sleep>>, new_deadline: Instant) {
|
|
72
|
+
if let Some(sleep) = sleep.as_mut().downcast_mut_pin::<TokioSleep>() {
|
|
73
|
+
sleep.reset(new_deadline)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
impl TokioTimer {
|
|
79
|
+
/// Create a new TokioTimer
|
|
80
|
+
pub fn new() -> Self {
|
|
81
|
+
Self {}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
impl Future for TokioSleep {
|
|
86
|
+
type Output = ();
|
|
87
|
+
|
|
88
|
+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
89
|
+
self.project().inner.poll(cx)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
impl Sleep for TokioSleep {}
|
|
94
|
+
|
|
95
|
+
impl TokioSleep {
|
|
96
|
+
fn reset(self: Pin<&mut Self>, deadline: Instant) {
|
|
97
|
+
self.project().inner.as_mut().reset(deadline.into());
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//! Runtime components
|
|
2
|
+
//!
|
|
3
|
+
//! The traits and types within this module are used to allow plugging in
|
|
4
|
+
//! runtime types. These include:
|
|
5
|
+
//!
|
|
6
|
+
//! - Executors
|
|
7
|
+
//! - Timers
|
|
8
|
+
//! - IO transports
|
|
9
|
+
|
|
10
|
+
pub mod bounds;
|
|
11
|
+
mod timer;
|
|
12
|
+
mod tokio;
|
|
13
|
+
|
|
14
|
+
pub use self::{
|
|
15
|
+
timer::{ArcTimer, Sleep, Time, Timer},
|
|
16
|
+
tokio::{TokioExecutor, TokioTimer},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/// An executor of futures.
|
|
20
|
+
///
|
|
21
|
+
/// This trait allows abstract over async runtimes. Implement this trait for your own type.
|
|
22
|
+
pub trait Executor<Fut> {
|
|
23
|
+
/// Place the future into the executor to be run.
|
|
24
|
+
fn execute(&self, fut: Fut);
|
|
25
|
+
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
//! HTTP Upgrades
|
|
2
|
+
//!
|
|
3
|
+
//! This module deals with managing [HTTP Upgrades][mdn] in crate::core:. Since
|
|
4
|
+
//! several concepts in HTTP allow for first talking HTTP, and then converting
|
|
5
|
+
//! to a different protocol, this module conflates them into a single API.
|
|
6
|
+
//! Those include:
|
|
7
|
+
//!
|
|
8
|
+
//! - HTTP/1.1 Upgrades
|
|
9
|
+
//! - HTTP `CONNECT`
|
|
10
|
+
//!
|
|
11
|
+
//! You are responsible for any other pre-requisites to establish an upgrade,
|
|
12
|
+
//! such as sending the appropriate headers, methods, and status codes. You can
|
|
13
|
+
//! then use [`on`][] to grab a `Future` which will resolve to the upgraded
|
|
14
|
+
//! connection object, or an error if the upgrade fails.
|
|
15
|
+
//!
|
|
16
|
+
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism
|
|
17
|
+
//!
|
|
18
|
+
//! Sending an HTTP upgrade from the client involves setting
|
|
19
|
+
//! either the appropriate method, if wanting to `CONNECT`, or headers such as
|
|
20
|
+
//! `Upgrade` and `Connection`, on the `http::Request`. Once receiving the
|
|
21
|
+
//! `http::Response` back, you must check for the specific information that the
|
|
22
|
+
//! upgrade is agreed upon by the server (such as a `101` status code), and then
|
|
23
|
+
//! get the `Future` from the `Response`.
|
|
24
|
+
|
|
25
|
+
use std::{
|
|
26
|
+
error::Error as StdError,
|
|
27
|
+
fmt,
|
|
28
|
+
future::Future,
|
|
29
|
+
io,
|
|
30
|
+
pin::Pin,
|
|
31
|
+
sync::Arc,
|
|
32
|
+
task::{Context, Poll},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
use bytes::Bytes;
|
|
36
|
+
use tokio::{
|
|
37
|
+
io::{AsyncRead, AsyncWrite, ReadBuf},
|
|
38
|
+
sync::oneshot,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
use super::{Error, Result, common::rewind::Rewind};
|
|
42
|
+
use crate::sync::Mutex;
|
|
43
|
+
|
|
44
|
+
/// An upgraded HTTP connection.
|
|
45
|
+
///
|
|
46
|
+
/// This type holds a trait object internally of the original IO that
|
|
47
|
+
/// was used to speak HTTP before the upgrade. It can be used directly
|
|
48
|
+
/// as a [`AsyncRead`] or [`AsyncWrite`] for convenience.
|
|
49
|
+
///
|
|
50
|
+
/// Alternatively, if the exact type is known, this can be deconstructed
|
|
51
|
+
/// into its parts.
|
|
52
|
+
pub struct Upgraded {
|
|
53
|
+
io: Rewind<Box<dyn Io + Send>>,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// A future for a possible HTTP upgrade.
|
|
57
|
+
///
|
|
58
|
+
/// If no upgrade was available, or it doesn't succeed, yields an `Error`.
|
|
59
|
+
#[derive(Clone)]
|
|
60
|
+
pub struct OnUpgrade {
|
|
61
|
+
rx: Option<Arc<Mutex<oneshot::Receiver<Result<Upgraded>>>>>,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/// Gets a pending HTTP upgrade from this message.
|
|
65
|
+
///
|
|
66
|
+
/// This can be called on the following types:
|
|
67
|
+
///
|
|
68
|
+
/// - `http::Request<B>`
|
|
69
|
+
/// - `http::Response<B>`
|
|
70
|
+
/// - `&mut http::Request<B>`
|
|
71
|
+
/// - `&mut http::Response<B>`
|
|
72
|
+
#[inline]
|
|
73
|
+
pub fn on<T: sealed::CanUpgrade>(msg: T) -> OnUpgrade {
|
|
74
|
+
msg.on_upgrade()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
pub(super) struct Pending {
|
|
78
|
+
tx: oneshot::Sender<Result<Upgraded>>,
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
pub(super) fn pending() -> (Pending, OnUpgrade) {
|
|
82
|
+
let (tx, rx) = oneshot::channel();
|
|
83
|
+
(
|
|
84
|
+
Pending { tx },
|
|
85
|
+
OnUpgrade {
|
|
86
|
+
rx: Some(Arc::new(Mutex::new(rx))),
|
|
87
|
+
},
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ===== impl Upgraded =====
|
|
92
|
+
|
|
93
|
+
impl Upgraded {
|
|
94
|
+
#[inline]
|
|
95
|
+
pub(super) fn new<T>(io: T, read_buf: Bytes) -> Self
|
|
96
|
+
where
|
|
97
|
+
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
|
|
98
|
+
{
|
|
99
|
+
Upgraded {
|
|
100
|
+
io: Rewind::new_buffered(Box::new(io), read_buf),
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
impl AsyncRead for Upgraded {
|
|
106
|
+
#[inline]
|
|
107
|
+
fn poll_read(
|
|
108
|
+
mut self: Pin<&mut Self>,
|
|
109
|
+
cx: &mut Context<'_>,
|
|
110
|
+
buf: &mut ReadBuf<'_>,
|
|
111
|
+
) -> Poll<io::Result<()>> {
|
|
112
|
+
Pin::new(&mut self.io).poll_read(cx, buf)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
impl AsyncWrite for Upgraded {
|
|
117
|
+
#[inline]
|
|
118
|
+
fn poll_write(
|
|
119
|
+
mut self: Pin<&mut Self>,
|
|
120
|
+
cx: &mut Context<'_>,
|
|
121
|
+
buf: &[u8],
|
|
122
|
+
) -> Poll<io::Result<usize>> {
|
|
123
|
+
Pin::new(&mut self.io).poll_write(cx, buf)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
#[inline]
|
|
127
|
+
fn poll_write_vectored(
|
|
128
|
+
mut self: Pin<&mut Self>,
|
|
129
|
+
cx: &mut Context<'_>,
|
|
130
|
+
bufs: &[io::IoSlice<'_>],
|
|
131
|
+
) -> Poll<io::Result<usize>> {
|
|
132
|
+
Pin::new(&mut self.io).poll_write_vectored(cx, bufs)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
#[inline]
|
|
136
|
+
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
|
137
|
+
Pin::new(&mut self.io).poll_flush(cx)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
#[inline]
|
|
141
|
+
fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
|
142
|
+
Pin::new(&mut self.io).poll_shutdown(cx)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
#[inline]
|
|
146
|
+
fn is_write_vectored(&self) -> bool {
|
|
147
|
+
self.io.is_write_vectored()
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
impl fmt::Debug for Upgraded {
|
|
152
|
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
153
|
+
f.debug_struct("Upgraded").finish()
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ===== impl OnUpgrade =====
|
|
158
|
+
|
|
159
|
+
impl OnUpgrade {
|
|
160
|
+
#[inline]
|
|
161
|
+
pub(super) fn none() -> Self {
|
|
162
|
+
OnUpgrade { rx: None }
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
#[inline]
|
|
166
|
+
pub(super) fn is_none(&self) -> bool {
|
|
167
|
+
self.rx.is_none()
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
impl Future for OnUpgrade {
|
|
172
|
+
type Output = std::result::Result<Upgraded, Error>;
|
|
173
|
+
|
|
174
|
+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
175
|
+
match self.rx {
|
|
176
|
+
Some(ref rx) => Pin::new(&mut *rx.lock()).poll(cx).map(|res| match res {
|
|
177
|
+
Ok(Ok(upgraded)) => Ok(upgraded),
|
|
178
|
+
Ok(Err(err)) => Err(err),
|
|
179
|
+
Err(_oneshot_canceled) => Err(Error::new_canceled().with(UpgradeExpected)),
|
|
180
|
+
}),
|
|
181
|
+
None => Poll::Ready(Err(Error::new_user_no_upgrade())),
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ===== impl Pending =====
|
|
187
|
+
|
|
188
|
+
impl Pending {
|
|
189
|
+
#[inline]
|
|
190
|
+
pub(super) fn fulfill(self, upgraded: Upgraded) {
|
|
191
|
+
trace!("pending upgrade fulfill");
|
|
192
|
+
let _ = self.tx.send(Ok(upgraded));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/// Don't fulfill the pending Upgrade, but instead signal that
|
|
196
|
+
/// upgrades are handled manually.
|
|
197
|
+
#[inline]
|
|
198
|
+
pub(super) fn manual(self) {
|
|
199
|
+
trace!("pending upgrade handled manually");
|
|
200
|
+
let _ = self.tx.send(Err(Error::new_user_manual_upgrade()));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ===== impl UpgradeExpected =====
|
|
205
|
+
|
|
206
|
+
/// Error cause returned when an upgrade was expected but canceled
|
|
207
|
+
/// for whatever reason.
|
|
208
|
+
///
|
|
209
|
+
/// This likely means the actual `Conn` future wasn't polled and upgraded.
|
|
210
|
+
#[derive(Debug)]
|
|
211
|
+
struct UpgradeExpected;
|
|
212
|
+
|
|
213
|
+
impl fmt::Display for UpgradeExpected {
|
|
214
|
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
215
|
+
f.write_str("upgrade expected but not completed")
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
impl StdError for UpgradeExpected {}
|
|
220
|
+
|
|
221
|
+
// ===== impl Io =====
|
|
222
|
+
|
|
223
|
+
trait Io: AsyncRead + AsyncWrite + Unpin + 'static {}
|
|
224
|
+
|
|
225
|
+
impl<T: AsyncRead + AsyncWrite + Unpin + 'static> Io for T {}
|
|
226
|
+
|
|
227
|
+
impl dyn Io + Send {}
|
|
228
|
+
|
|
229
|
+
mod sealed {
|
|
230
|
+
use super::OnUpgrade;
|
|
231
|
+
|
|
232
|
+
pub trait CanUpgrade {
|
|
233
|
+
fn on_upgrade(self) -> OnUpgrade;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
impl<B> CanUpgrade for http::Request<B> {
|
|
237
|
+
fn on_upgrade(mut self) -> OnUpgrade {
|
|
238
|
+
self.extensions_mut()
|
|
239
|
+
.remove::<OnUpgrade>()
|
|
240
|
+
.unwrap_or_else(OnUpgrade::none)
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
impl<B> CanUpgrade for &'_ mut http::Request<B> {
|
|
245
|
+
fn on_upgrade(self) -> OnUpgrade {
|
|
246
|
+
self.extensions_mut()
|
|
247
|
+
.remove::<OnUpgrade>()
|
|
248
|
+
.unwrap_or_else(OnUpgrade::none)
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
impl<B> CanUpgrade for http::Response<B> {
|
|
253
|
+
fn on_upgrade(mut self) -> OnUpgrade {
|
|
254
|
+
self.extensions_mut()
|
|
255
|
+
.remove::<OnUpgrade>()
|
|
256
|
+
.unwrap_or_else(OnUpgrade::none)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
impl<B> CanUpgrade for &'_ mut http::Response<B> {
|
|
261
|
+
fn on_upgrade(self) -> OnUpgrade {
|
|
262
|
+
self.extensions_mut()
|
|
263
|
+
.remove::<OnUpgrade>()
|
|
264
|
+
.unwrap_or_else(OnUpgrade::none)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//! HTTP Client protocol implementation and low level utilities.
|
|
2
|
+
|
|
3
|
+
mod common;
|
|
4
|
+
mod dispatch;
|
|
5
|
+
mod error;
|
|
6
|
+
mod proto;
|
|
7
|
+
|
|
8
|
+
pub mod body;
|
|
9
|
+
pub mod conn;
|
|
10
|
+
pub mod ext;
|
|
11
|
+
pub mod http1;
|
|
12
|
+
pub mod http2;
|
|
13
|
+
pub mod rt;
|
|
14
|
+
pub mod upgrade;
|
|
15
|
+
|
|
16
|
+
pub use self::error::{Error, Result};
|