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.
Files changed (167) hide show
  1. checksums.yaml +7 -0
  2. data/Cargo.lock +2688 -0
  3. data/Cargo.toml +6 -0
  4. data/README.md +179 -0
  5. data/ext/wreq_rb/Cargo.toml +39 -0
  6. data/ext/wreq_rb/extconf.rb +22 -0
  7. data/ext/wreq_rb/src/client.rs +565 -0
  8. data/ext/wreq_rb/src/error.rs +25 -0
  9. data/ext/wreq_rb/src/lib.rs +20 -0
  10. data/ext/wreq_rb/src/response.rs +132 -0
  11. data/lib/wreq-rb/version.rb +5 -0
  12. data/lib/wreq-rb.rb +17 -0
  13. data/patches/0001-add-transfer-size-tracking.patch +292 -0
  14. data/vendor/wreq/Cargo.toml +306 -0
  15. data/vendor/wreq/LICENSE +202 -0
  16. data/vendor/wreq/README.md +122 -0
  17. data/vendor/wreq/examples/cert_store.rs +77 -0
  18. data/vendor/wreq/examples/connect_via_lower_priority_tokio_runtime.rs +258 -0
  19. data/vendor/wreq/examples/emulation.rs +118 -0
  20. data/vendor/wreq/examples/form.rs +14 -0
  21. data/vendor/wreq/examples/http1_websocket.rs +37 -0
  22. data/vendor/wreq/examples/http2_websocket.rs +45 -0
  23. data/vendor/wreq/examples/json_dynamic.rs +41 -0
  24. data/vendor/wreq/examples/json_typed.rs +47 -0
  25. data/vendor/wreq/examples/keylog.rs +16 -0
  26. data/vendor/wreq/examples/request_with_emulation.rs +115 -0
  27. data/vendor/wreq/examples/request_with_interface.rs +37 -0
  28. data/vendor/wreq/examples/request_with_local_address.rs +16 -0
  29. data/vendor/wreq/examples/request_with_proxy.rs +13 -0
  30. data/vendor/wreq/examples/request_with_redirect.rs +22 -0
  31. data/vendor/wreq/examples/request_with_version.rs +15 -0
  32. data/vendor/wreq/examples/tor_socks.rs +24 -0
  33. data/vendor/wreq/examples/unix_socket.rs +33 -0
  34. data/vendor/wreq/src/client/body.rs +304 -0
  35. data/vendor/wreq/src/client/conn/conn.rs +231 -0
  36. data/vendor/wreq/src/client/conn/connector.rs +549 -0
  37. data/vendor/wreq/src/client/conn/http.rs +1023 -0
  38. data/vendor/wreq/src/client/conn/proxy/socks.rs +233 -0
  39. data/vendor/wreq/src/client/conn/proxy/tunnel.rs +260 -0
  40. data/vendor/wreq/src/client/conn/proxy.rs +39 -0
  41. data/vendor/wreq/src/client/conn/tls_info.rs +98 -0
  42. data/vendor/wreq/src/client/conn/uds.rs +44 -0
  43. data/vendor/wreq/src/client/conn/verbose.rs +149 -0
  44. data/vendor/wreq/src/client/conn.rs +323 -0
  45. data/vendor/wreq/src/client/core/body/incoming.rs +485 -0
  46. data/vendor/wreq/src/client/core/body/length.rs +118 -0
  47. data/vendor/wreq/src/client/core/body.rs +34 -0
  48. data/vendor/wreq/src/client/core/common/buf.rs +149 -0
  49. data/vendor/wreq/src/client/core/common/rewind.rs +141 -0
  50. data/vendor/wreq/src/client/core/common/watch.rs +76 -0
  51. data/vendor/wreq/src/client/core/common.rs +3 -0
  52. data/vendor/wreq/src/client/core/conn/http1.rs +342 -0
  53. data/vendor/wreq/src/client/core/conn/http2.rs +307 -0
  54. data/vendor/wreq/src/client/core/conn.rs +11 -0
  55. data/vendor/wreq/src/client/core/dispatch.rs +299 -0
  56. data/vendor/wreq/src/client/core/error.rs +435 -0
  57. data/vendor/wreq/src/client/core/ext.rs +201 -0
  58. data/vendor/wreq/src/client/core/http1.rs +178 -0
  59. data/vendor/wreq/src/client/core/http2.rs +483 -0
  60. data/vendor/wreq/src/client/core/proto/h1/conn.rs +988 -0
  61. data/vendor/wreq/src/client/core/proto/h1/decode.rs +1170 -0
  62. data/vendor/wreq/src/client/core/proto/h1/dispatch.rs +684 -0
  63. data/vendor/wreq/src/client/core/proto/h1/encode.rs +580 -0
  64. data/vendor/wreq/src/client/core/proto/h1/io.rs +879 -0
  65. data/vendor/wreq/src/client/core/proto/h1/role.rs +694 -0
  66. data/vendor/wreq/src/client/core/proto/h1.rs +104 -0
  67. data/vendor/wreq/src/client/core/proto/h2/client.rs +650 -0
  68. data/vendor/wreq/src/client/core/proto/h2/ping.rs +539 -0
  69. data/vendor/wreq/src/client/core/proto/h2.rs +379 -0
  70. data/vendor/wreq/src/client/core/proto/headers.rs +138 -0
  71. data/vendor/wreq/src/client/core/proto.rs +58 -0
  72. data/vendor/wreq/src/client/core/rt/bounds.rs +57 -0
  73. data/vendor/wreq/src/client/core/rt/timer.rs +150 -0
  74. data/vendor/wreq/src/client/core/rt/tokio.rs +99 -0
  75. data/vendor/wreq/src/client/core/rt.rs +25 -0
  76. data/vendor/wreq/src/client/core/upgrade.rs +267 -0
  77. data/vendor/wreq/src/client/core.rs +16 -0
  78. data/vendor/wreq/src/client/emulation.rs +161 -0
  79. data/vendor/wreq/src/client/http/client/error.rs +142 -0
  80. data/vendor/wreq/src/client/http/client/exec.rs +29 -0
  81. data/vendor/wreq/src/client/http/client/extra.rs +77 -0
  82. data/vendor/wreq/src/client/http/client/lazy.rs +79 -0
  83. data/vendor/wreq/src/client/http/client/pool.rs +1105 -0
  84. data/vendor/wreq/src/client/http/client/util.rs +104 -0
  85. data/vendor/wreq/src/client/http/client.rs +1003 -0
  86. data/vendor/wreq/src/client/http/future.rs +99 -0
  87. data/vendor/wreq/src/client/http.rs +1629 -0
  88. data/vendor/wreq/src/client/layer/config/options.rs +156 -0
  89. data/vendor/wreq/src/client/layer/config.rs +116 -0
  90. data/vendor/wreq/src/client/layer/cookie.rs +161 -0
  91. data/vendor/wreq/src/client/layer/decoder.rs +139 -0
  92. data/vendor/wreq/src/client/layer/redirect/future.rs +270 -0
  93. data/vendor/wreq/src/client/layer/redirect/policy.rs +63 -0
  94. data/vendor/wreq/src/client/layer/redirect.rs +145 -0
  95. data/vendor/wreq/src/client/layer/retry/classify.rs +105 -0
  96. data/vendor/wreq/src/client/layer/retry/scope.rs +51 -0
  97. data/vendor/wreq/src/client/layer/retry.rs +151 -0
  98. data/vendor/wreq/src/client/layer/timeout/body.rs +233 -0
  99. data/vendor/wreq/src/client/layer/timeout/future.rs +90 -0
  100. data/vendor/wreq/src/client/layer/timeout.rs +177 -0
  101. data/vendor/wreq/src/client/layer.rs +15 -0
  102. data/vendor/wreq/src/client/multipart.rs +717 -0
  103. data/vendor/wreq/src/client/request.rs +818 -0
  104. data/vendor/wreq/src/client/response.rs +534 -0
  105. data/vendor/wreq/src/client/ws/json.rs +99 -0
  106. data/vendor/wreq/src/client/ws/message.rs +453 -0
  107. data/vendor/wreq/src/client/ws.rs +714 -0
  108. data/vendor/wreq/src/client.rs +27 -0
  109. data/vendor/wreq/src/config.rs +140 -0
  110. data/vendor/wreq/src/cookie.rs +579 -0
  111. data/vendor/wreq/src/dns/gai.rs +249 -0
  112. data/vendor/wreq/src/dns/hickory.rs +78 -0
  113. data/vendor/wreq/src/dns/resolve.rs +180 -0
  114. data/vendor/wreq/src/dns.rs +69 -0
  115. data/vendor/wreq/src/error.rs +502 -0
  116. data/vendor/wreq/src/ext.rs +398 -0
  117. data/vendor/wreq/src/hash.rs +143 -0
  118. data/vendor/wreq/src/header.rs +506 -0
  119. data/vendor/wreq/src/into_uri.rs +187 -0
  120. data/vendor/wreq/src/lib.rs +586 -0
  121. data/vendor/wreq/src/proxy/mac.rs +82 -0
  122. data/vendor/wreq/src/proxy/matcher.rs +806 -0
  123. data/vendor/wreq/src/proxy/uds.rs +66 -0
  124. data/vendor/wreq/src/proxy/win.rs +31 -0
  125. data/vendor/wreq/src/proxy.rs +569 -0
  126. data/vendor/wreq/src/redirect.rs +575 -0
  127. data/vendor/wreq/src/retry.rs +198 -0
  128. data/vendor/wreq/src/sync.rs +129 -0
  129. data/vendor/wreq/src/tls/conn/cache.rs +123 -0
  130. data/vendor/wreq/src/tls/conn/cert_compression.rs +125 -0
  131. data/vendor/wreq/src/tls/conn/ext.rs +82 -0
  132. data/vendor/wreq/src/tls/conn/macros.rs +34 -0
  133. data/vendor/wreq/src/tls/conn/service.rs +138 -0
  134. data/vendor/wreq/src/tls/conn.rs +681 -0
  135. data/vendor/wreq/src/tls/keylog/handle.rs +64 -0
  136. data/vendor/wreq/src/tls/keylog.rs +99 -0
  137. data/vendor/wreq/src/tls/options.rs +464 -0
  138. data/vendor/wreq/src/tls/x509/identity.rs +122 -0
  139. data/vendor/wreq/src/tls/x509/parser.rs +71 -0
  140. data/vendor/wreq/src/tls/x509/store.rs +228 -0
  141. data/vendor/wreq/src/tls/x509.rs +68 -0
  142. data/vendor/wreq/src/tls.rs +154 -0
  143. data/vendor/wreq/src/trace.rs +55 -0
  144. data/vendor/wreq/src/util.rs +122 -0
  145. data/vendor/wreq/tests/badssl.rs +228 -0
  146. data/vendor/wreq/tests/brotli.rs +350 -0
  147. data/vendor/wreq/tests/client.rs +1098 -0
  148. data/vendor/wreq/tests/connector_layers.rs +227 -0
  149. data/vendor/wreq/tests/cookie.rs +306 -0
  150. data/vendor/wreq/tests/deflate.rs +347 -0
  151. data/vendor/wreq/tests/emulation.rs +260 -0
  152. data/vendor/wreq/tests/gzip.rs +347 -0
  153. data/vendor/wreq/tests/layers.rs +261 -0
  154. data/vendor/wreq/tests/multipart.rs +165 -0
  155. data/vendor/wreq/tests/proxy.rs +438 -0
  156. data/vendor/wreq/tests/redirect.rs +629 -0
  157. data/vendor/wreq/tests/retry.rs +135 -0
  158. data/vendor/wreq/tests/support/delay_server.rs +117 -0
  159. data/vendor/wreq/tests/support/error.rs +16 -0
  160. data/vendor/wreq/tests/support/layer.rs +183 -0
  161. data/vendor/wreq/tests/support/mod.rs +9 -0
  162. data/vendor/wreq/tests/support/server.rs +232 -0
  163. data/vendor/wreq/tests/timeouts.rs +281 -0
  164. data/vendor/wreq/tests/unix_socket.rs +135 -0
  165. data/vendor/wreq/tests/upgrade.rs +98 -0
  166. data/vendor/wreq/tests/zstd.rs +559 -0
  167. metadata +225 -0
@@ -0,0 +1,156 @@
1
+ use http::Version;
2
+
3
+ use crate::{
4
+ client::{
5
+ conn::TcpConnectOptions,
6
+ core::{http1::Http1Options, http2::Http2Options},
7
+ },
8
+ proxy::Matcher,
9
+ tls::TlsOptions,
10
+ };
11
+
12
+ /// Per-request configuration for proxy, protocol, and transport options.
13
+ /// Overrides client defaults for a single request.
14
+ #[derive(Debug, Default, Clone, Hash, PartialEq, Eq)]
15
+ #[non_exhaustive]
16
+ pub struct RequestOptions {
17
+ proxy_matcher: Option<Matcher>,
18
+ enforced_version: Option<Version>,
19
+ tcp_connect_opts: TcpConnectOptions,
20
+ transport_opts: TransportOptions,
21
+ }
22
+
23
+ /// Transport options for HTTP/1, HTTP/2, and TLS layers.
24
+ ///
25
+ /// This struct allows you to customize protocol-specific and TLS settings
26
+ /// for network connections made by the client.
27
+ #[derive(Debug, Default, Clone, Hash, PartialEq, Eq)]
28
+ #[non_exhaustive]
29
+ pub struct TransportOptions {
30
+ tls_options: Option<TlsOptions>,
31
+ http1_options: Option<Http1Options>,
32
+ http2_options: Option<Http2Options>,
33
+ }
34
+
35
+ // ===== impl RequestOptions =====
36
+
37
+ impl_request_config_value!(RequestOptions);
38
+
39
+ // ===== impl TransportOptions =====
40
+
41
+ impl TransportOptions {
42
+ /// Get the reference to the TLS options.
43
+ #[inline]
44
+ pub fn tls_options(&self) -> Option<&TlsOptions> {
45
+ self.tls_options.as_ref()
46
+ }
47
+
48
+ /// Get a mutable reference to the TLS options.
49
+ #[inline]
50
+ pub fn tls_options_mut(&mut self) -> &mut Option<TlsOptions> {
51
+ &mut self.tls_options
52
+ }
53
+
54
+ /// Get the reference to the HTTP/1 options.
55
+ #[inline]
56
+ pub fn http1_options(&self) -> Option<&Http1Options> {
57
+ self.http1_options.as_ref()
58
+ }
59
+
60
+ /// Get a mutable reference to the HTTP/1 options.
61
+ #[inline]
62
+ pub fn http1_options_mut(&mut self) -> &mut Option<Http1Options> {
63
+ &mut self.http1_options
64
+ }
65
+
66
+ /// Get the reference to the HTTP/2 options.
67
+ #[inline]
68
+ pub fn http2_options(&self) -> Option<&Http2Options> {
69
+ self.http2_options.as_ref()
70
+ }
71
+
72
+ /// Get a mutable reference to the HTTP/2 options.
73
+ #[inline]
74
+ pub fn http2_options_mut(&mut self) -> &mut Option<Http2Options> {
75
+ &mut self.http2_options
76
+ }
77
+
78
+ /// Apply the transport options for HTTP/1, HTTP/2, and TLS.
79
+ pub(crate) fn apply_transport_options(&mut self, opts: TransportOptions) -> &mut Self {
80
+ if let Some(tls) = opts.tls_options {
81
+ *self.tls_options_mut() = Some(tls);
82
+ }
83
+ if let Some(http1) = opts.http1_options {
84
+ *self.http1_options_mut() = Some(http1);
85
+ }
86
+ if let Some(http2) = opts.http2_options {
87
+ *self.http2_options_mut() = Some(http2);
88
+ }
89
+ self
90
+ }
91
+ }
92
+
93
+ impl From<TransportOptions>
94
+ for (
95
+ Option<TlsOptions>,
96
+ Option<Http1Options>,
97
+ Option<Http2Options>,
98
+ )
99
+ {
100
+ #[inline]
101
+ fn from(value: TransportOptions) -> Self {
102
+ (value.tls_options, value.http1_options, value.http2_options)
103
+ }
104
+ }
105
+
106
+ // ===== impl RequestOptions =====
107
+
108
+ impl RequestOptions {
109
+ /// Get a reference to the proxy matcher.
110
+ #[inline]
111
+ pub fn proxy_matcher(&self) -> Option<&Matcher> {
112
+ self.proxy_matcher.as_ref()
113
+ }
114
+
115
+ /// Get a mutable reference to the proxy matcher.
116
+ #[inline]
117
+ pub fn proxy_matcher_mut(&mut self) -> &mut Option<Matcher> {
118
+ &mut self.proxy_matcher
119
+ }
120
+
121
+ /// Get the enforced HTTP version.
122
+ #[inline]
123
+ pub fn enforced_version(&self) -> Option<Version> {
124
+ self.enforced_version
125
+ }
126
+
127
+ /// Get a mutable reference to the enforced HTTP version.
128
+ #[inline]
129
+ pub fn enforced_version_mut(&mut self) -> &mut Option<Version> {
130
+ &mut self.enforced_version
131
+ }
132
+
133
+ /// Get a reference to the TCP connection options.
134
+ #[inline]
135
+ pub fn tcp_connect_opts(&self) -> &TcpConnectOptions {
136
+ &self.tcp_connect_opts
137
+ }
138
+
139
+ /// Get a mutable reference to the TCP connection options.
140
+ #[inline]
141
+ pub fn tcp_connect_opts_mut(&mut self) -> &mut TcpConnectOptions {
142
+ &mut self.tcp_connect_opts
143
+ }
144
+
145
+ /// Get a reference to the transport options.
146
+ #[inline]
147
+ pub fn transport_opts(&self) -> &TransportOptions {
148
+ &self.transport_opts
149
+ }
150
+
151
+ /// Get a mutable reference to the transport options.
152
+ #[inline]
153
+ pub fn transport_opts_mut(&mut self) -> &mut TransportOptions {
154
+ &mut self.transport_opts
155
+ }
156
+ }
@@ -0,0 +1,116 @@
1
+ mod options;
2
+
3
+ use std::{
4
+ sync::Arc,
5
+ task::{Context, Poll},
6
+ };
7
+
8
+ use futures_util::future::{self, Either, Ready};
9
+ use http::{HeaderMap, Request, Response};
10
+ use tower::{Layer, Service};
11
+
12
+ pub use self::options::{RequestOptions, TransportOptions};
13
+ use crate::{Error, config::RequestConfig, ext::UriExt, header::OrigHeaderMap};
14
+
15
+ /// A marker type for the default headers configuration value.
16
+ #[derive(Clone, Copy)]
17
+ pub(crate) struct DefaultHeaders;
18
+
19
+ /// Configuration for the [`ConfigService`].
20
+ struct Config {
21
+ https_only: bool,
22
+ headers: HeaderMap,
23
+ orig_headers: RequestConfig<OrigHeaderMap>,
24
+ default_headers: RequestConfig<DefaultHeaders>,
25
+ }
26
+
27
+ /// Middleware layer to use [`ConfigService`].
28
+ pub struct ConfigServiceLayer {
29
+ config: Arc<Config>,
30
+ }
31
+
32
+ /// Middleware service to use [`Config`].
33
+ #[derive(Clone)]
34
+ pub struct ConfigService<S> {
35
+ inner: S,
36
+ config: Arc<Config>,
37
+ }
38
+
39
+ // ===== impl DefaultHeaders =====
40
+
41
+ impl_request_config_value!(DefaultHeaders, bool);
42
+
43
+ // ===== impl ConfigServiceLayer =====
44
+
45
+ impl ConfigServiceLayer {
46
+ /// Creates a new [`ConfigServiceLayer`].
47
+ pub fn new(https_only: bool, headers: HeaderMap, orig_headers: OrigHeaderMap) -> Self {
48
+ let org_headers = (!orig_headers.is_empty()).then_some(orig_headers);
49
+ ConfigServiceLayer {
50
+ config: Arc::new(Config {
51
+ https_only,
52
+ headers,
53
+ orig_headers: RequestConfig::new(org_headers),
54
+ default_headers: RequestConfig::new(Some(true)),
55
+ }),
56
+ }
57
+ }
58
+ }
59
+
60
+ impl<S> Layer<S> for ConfigServiceLayer {
61
+ type Service = ConfigService<S>;
62
+
63
+ #[inline(always)]
64
+ fn layer(&self, inner: S) -> Self::Service {
65
+ ConfigService {
66
+ inner,
67
+ config: self.config.clone(),
68
+ }
69
+ }
70
+ }
71
+
72
+ // ===== impl ConfigService =====
73
+
74
+ impl<ReqBody, ResBody, S> Service<Request<ReqBody>> for ConfigService<S>
75
+ where
76
+ S: Service<Request<ReqBody>, Response = Response<ResBody>>,
77
+ S::Error: From<Error>,
78
+ {
79
+ type Response = S::Response;
80
+ type Error = S::Error;
81
+ type Future = Either<S::Future, Ready<Result<Self::Response, Self::Error>>>;
82
+
83
+ #[inline(always)]
84
+ fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
85
+ self.inner.poll_ready(cx)
86
+ }
87
+
88
+ fn call(&mut self, mut req: Request<ReqBody>) -> Self::Future {
89
+ let uri = req.uri().clone();
90
+
91
+ // check if the request URI scheme is valid.
92
+ if !(uri.is_http() || uri.is_https()) || (self.config.https_only && !uri.is_https()) {
93
+ return Either::Right(future::err(Error::uri_bad_scheme(uri.clone()).into()));
94
+ }
95
+
96
+ // check if the request ignores the default headers.
97
+ if self
98
+ .config
99
+ .default_headers
100
+ .fetch(req.extensions())
101
+ .copied()
102
+ .unwrap_or_default()
103
+ {
104
+ // insert default headers in the request headers
105
+ // without overwriting already appended headers.
106
+ let mut dest = self.config.headers.clone();
107
+ crate::util::replace_headers(&mut dest, std::mem::take(req.headers_mut()));
108
+ std::mem::swap(req.headers_mut(), &mut dest);
109
+ }
110
+
111
+ // store the original headers in request extensions
112
+ self.config.orig_headers.store(req.extensions_mut());
113
+
114
+ Either::Left(self.inner.call(req))
115
+ }
116
+ }
@@ -0,0 +1,161 @@
1
+ //! Middleware to use Cookie.
2
+
3
+ use std::{
4
+ future::Future,
5
+ pin::Pin,
6
+ sync::Arc,
7
+ task::{Context, Poll, ready},
8
+ };
9
+
10
+ use http::{Request, Response, Uri, header::COOKIE};
11
+ use pin_project_lite::pin_project;
12
+ use tower::{Layer, Service};
13
+
14
+ use crate::{
15
+ config::RequestConfig,
16
+ cookie::{CookieStore, Cookies},
17
+ };
18
+
19
+ pin_project! {
20
+ /// Response future for [`CookieService`].
21
+ #[project = ResponseFutureProj]
22
+ pub enum ResponseFuture<Fut> {
23
+ Managed {
24
+ #[pin]
25
+ fut: Fut,
26
+ uri: Uri,
27
+ store: Arc<dyn CookieStore>,
28
+ },
29
+ Plain {
30
+ #[pin]
31
+ fut: Fut,
32
+ },
33
+ }
34
+ }
35
+
36
+ /// Layer to apply [`CookieService`] middleware.
37
+ #[derive(Clone)]
38
+ pub struct CookieServiceLayer {
39
+ store: RequestConfig<Arc<dyn CookieStore>>,
40
+ }
41
+
42
+ /// Middleware to use [`CookieStore`].
43
+ #[derive(Clone)]
44
+ pub struct CookieService<S> {
45
+ inner: S,
46
+ store: RequestConfig<Arc<dyn CookieStore>>,
47
+ }
48
+
49
+ // ===== impl ResponseFuture =====
50
+
51
+ impl<F, ResBody, E> Future for ResponseFuture<F>
52
+ where
53
+ F: Future<Output = Result<Response<ResBody>, E>>,
54
+ {
55
+ type Output = F::Output;
56
+
57
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
58
+ match self.project() {
59
+ ResponseFutureProj::Managed { fut, uri, store } => {
60
+ let res = ready!(fut.poll(cx)?);
61
+ let mut cookies = res
62
+ .headers()
63
+ .get_all(http::header::SET_COOKIE)
64
+ .iter()
65
+ .peekable();
66
+ if cookies.peek().is_some() {
67
+ store.set_cookies(&mut cookies, uri);
68
+ }
69
+
70
+ Poll::Ready(Ok(res))
71
+ }
72
+ ResponseFutureProj::Plain { fut: mut future } => future.as_mut().poll(cx),
73
+ }
74
+ }
75
+ }
76
+
77
+ // ===== impl CookieServiceLayer =====
78
+
79
+ impl CookieServiceLayer {
80
+ /// Create a new [`CookieServiceLayer`].
81
+ #[inline(always)]
82
+ pub const fn new(store: Option<Arc<dyn CookieStore + 'static>>) -> Self {
83
+ Self {
84
+ store: RequestConfig::new(store),
85
+ }
86
+ }
87
+ }
88
+
89
+ impl<S> Layer<S> for CookieServiceLayer {
90
+ type Service = CookieService<S>;
91
+
92
+ #[inline(always)]
93
+ fn layer(&self, inner: S) -> Self::Service {
94
+ CookieService {
95
+ inner,
96
+ store: self.store.clone(),
97
+ }
98
+ }
99
+ }
100
+
101
+ // ===== impl CookieService =====
102
+
103
+ impl<S> CookieService<S> {
104
+ fn inject_cookies<B>(
105
+ &self,
106
+ req: &mut Request<B>,
107
+ store: Arc<dyn CookieStore>,
108
+ ) -> (Arc<dyn CookieStore>, Uri) {
109
+ let uri = req.uri().clone();
110
+ let headers = req.headers_mut();
111
+
112
+ // Only inject cookies if request doesn't already have them
113
+ if !headers.contains_key(COOKIE) {
114
+ match store.cookies(&uri) {
115
+ Cookies::Compressed(value) => {
116
+ headers.insert(COOKIE, value);
117
+ }
118
+ Cookies::Uncompressed(values) => {
119
+ for value in values {
120
+ headers.append(COOKIE, value);
121
+ }
122
+ }
123
+ Cookies::Empty => (),
124
+ }
125
+ }
126
+
127
+ (store, uri)
128
+ }
129
+ }
130
+
131
+ impl<ReqBody, ResBody, S> Service<Request<ReqBody>> for CookieService<S>
132
+ where
133
+ S: Service<Request<ReqBody>, Response = Response<ResBody>>,
134
+ {
135
+ type Response = S::Response;
136
+ type Error = S::Error;
137
+ type Future = ResponseFuture<S::Future>;
138
+
139
+ #[inline(always)]
140
+ fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
141
+ self.inner.poll_ready(cx)
142
+ }
143
+
144
+ fn call(&mut self, mut req: Request<ReqBody>) -> Self::Future {
145
+ match self
146
+ .store
147
+ .fetch(req.extensions())
148
+ .cloned()
149
+ .map(|store| self.inject_cookies(&mut req, store))
150
+ {
151
+ Some((store, uri)) => ResponseFuture::Managed {
152
+ uri,
153
+ store,
154
+ fut: self.inner.call(req),
155
+ },
156
+ None => ResponseFuture::Plain {
157
+ fut: self.inner.call(req),
158
+ },
159
+ }
160
+ }
161
+ }
@@ -0,0 +1,139 @@
1
+ //! Middleware for decoding
2
+
3
+ use std::task::{Context, Poll};
4
+
5
+ use http::{Request, Response};
6
+ use http_body::Body;
7
+ use tower::{Layer, Service};
8
+ use tower_http::decompression::{self, DecompressionBody, ResponseFuture};
9
+
10
+ use crate::config::RequestConfig;
11
+
12
+ /// Configuration for supported content-encoding algorithms.
13
+ ///
14
+ /// `AcceptEncoding` controls which compression formats are enabled for decoding
15
+ /// response bodies. Each field corresponds to a specific algorithm and is only
16
+ /// available if the corresponding feature is enabled.
17
+ #[derive(Clone)]
18
+ pub(crate) struct AcceptEncoding {
19
+ #[cfg(feature = "gzip")]
20
+ pub(crate) gzip: bool,
21
+ #[cfg(feature = "brotli")]
22
+ pub(crate) brotli: bool,
23
+ #[cfg(feature = "zstd")]
24
+ pub(crate) zstd: bool,
25
+ #[cfg(feature = "deflate")]
26
+ pub(crate) deflate: bool,
27
+ }
28
+
29
+ /// Layer that adds response body decompression to a service.
30
+ #[derive(Clone)]
31
+ pub struct DecompressionLayer {
32
+ accept: AcceptEncoding,
33
+ }
34
+
35
+ /// Service that decompresses response bodies based on the [`AcceptEncoding`] configuration.
36
+ #[derive(Clone)]
37
+ pub struct Decompression<S>(Option<decompression::Decompression<S>>);
38
+
39
+ // ===== AcceptEncoding =====
40
+
41
+ impl Default for AcceptEncoding {
42
+ fn default() -> AcceptEncoding {
43
+ AcceptEncoding {
44
+ #[cfg(feature = "gzip")]
45
+ gzip: true,
46
+ #[cfg(feature = "brotli")]
47
+ brotli: true,
48
+ #[cfg(feature = "zstd")]
49
+ zstd: true,
50
+ #[cfg(feature = "deflate")]
51
+ deflate: true,
52
+ }
53
+ }
54
+ }
55
+
56
+ impl_request_config_value!(AcceptEncoding);
57
+
58
+ // ===== impl DecompressionLayer =====
59
+
60
+ impl DecompressionLayer {
61
+ /// Creates a new [`DecompressionLayer`] with the specified [`AcceptEncoding`].
62
+ #[inline(always)]
63
+ pub const fn new(accept: AcceptEncoding) -> Self {
64
+ Self { accept }
65
+ }
66
+ }
67
+
68
+ impl<S> Layer<S> for DecompressionLayer {
69
+ type Service = Decompression<S>;
70
+
71
+ #[inline(always)]
72
+ fn layer(&self, service: S) -> Self::Service {
73
+ Decompression(Some(Decompression::<S>::accept_in_place(
74
+ decompression::Decompression::new(service),
75
+ &self.accept,
76
+ )))
77
+ }
78
+ }
79
+
80
+ // ===== impl Decompression =====
81
+
82
+ impl<S> Decompression<S> {
83
+ const BUG_MSG: &str = "[BUG] Decompression service not initialized; bug in setup";
84
+
85
+ fn accept_in_place(
86
+ mut decoder: decompression::Decompression<S>,
87
+ accept: &AcceptEncoding,
88
+ ) -> decompression::Decompression<S> {
89
+ #[cfg(feature = "gzip")]
90
+ {
91
+ decoder = decoder.gzip(accept.gzip);
92
+ }
93
+
94
+ #[cfg(feature = "deflate")]
95
+ {
96
+ decoder = decoder.deflate(accept.deflate);
97
+ }
98
+
99
+ #[cfg(feature = "brotli")]
100
+ {
101
+ decoder = decoder.br(accept.brotli);
102
+ }
103
+
104
+ #[cfg(feature = "zstd")]
105
+ {
106
+ decoder = decoder.zstd(accept.zstd);
107
+ }
108
+
109
+ decoder
110
+ }
111
+ }
112
+
113
+ impl<S, ReqBody, ResBody> Service<Request<ReqBody>> for Decompression<S>
114
+ where
115
+ S: Service<Request<ReqBody>, Response = Response<ResBody>>,
116
+ ReqBody: Body,
117
+ ResBody: Body,
118
+ {
119
+ type Response = Response<DecompressionBody<ResBody>>;
120
+ type Error = S::Error;
121
+ type Future = ResponseFuture<S::Future>;
122
+
123
+ #[inline(always)]
124
+ fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
125
+ self.0.as_mut().expect(Self::BUG_MSG).poll_ready(cx)
126
+ }
127
+
128
+ fn call(&mut self, req: Request<ReqBody>) -> Self::Future {
129
+ if let Some(accept) = RequestConfig::<AcceptEncoding>::get(req.extensions()) {
130
+ if let Some(decoder) = self.0.take() {
131
+ self.0
132
+ .replace(Decompression::accept_in_place(decoder, accept));
133
+ }
134
+ debug_assert!(self.0.is_some());
135
+ }
136
+
137
+ self.0.as_mut().expect(Self::BUG_MSG).call(req)
138
+ }
139
+ }