1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//! Transport abstraction decoupling [`OrderBookApi`] from a concrete HTTP
//! backend.
//!
//! [`OrderBookApi`] builds a transport-agnostic [`HttpRequest`] for each
//! endpoint and hands it to an [`HttpTransport`]; the transport performs
//! the actual I/O and returns an [`HttpResponse`] whose body has already
//! been bounded by [`MAX_RESPONSE_BYTES`]. This is what lets the native
//! (reqwest) and wasm (`fetch`) builds share one client and one set of
//! endpoint logic instead of re-implementing request shaping, status
//! handling and JSON decoding per target.
//!
//! The concrete backends live as submodules behind the `http-client`
//! feature; the trait itself stays feature-independent so out-of-tree
//! backends can implement it.
//!
//! [`OrderBookApi`]: crate::OrderBookApi
//! [`MAX_RESPONSE_BYTES`]: crate::order_book::MAX_RESPONSE_BYTES
use DeserializeOwned;
use crate;
// Pathed as `self::reqwest` so the submodule never shadows the extern
// crate of the same name under uniform paths.
pub
/// Native HTTP backend (`reqwest`). Present only on non-`wasm32`
/// targets; `wasm32` builds expose `FetchTransport` instead. Prefer
/// [`DefaultTransport`] in cross-target code so the right backend is
/// selected automatically.
pub use ReqwestTransport;
/// Browser `fetch` HTTP backend. Present only on `wasm32` targets;
/// native builds expose `ReqwestTransport` instead. Prefer
/// [`DefaultTransport`] in cross-target code so the right backend is
/// selected automatically.
pub use FetchTransport;
/// The HTTP backend the `http-client` feature ships for the build
/// target: [`ReqwestTransport`] natively, `FetchTransport` on wasm32.
/// [`OrderBookApi`](crate::OrderBookApi) and
/// [`SubgraphClient`](crate::subgraph::SubgraphClient) default to it, so
/// `cowprotocol` consumers get a working client on either target without
/// naming a transport.
pub type DefaultTransport = ReqwestTransport;
/// The HTTP backend the `http-client` feature ships for the build
/// target: `ReqwestTransport` natively, [`FetchTransport`] on wasm32.
/// [`OrderBookApi`](crate::OrderBookApi) and
/// [`SubgraphClient`](crate::subgraph::SubgraphClient) default to it, so
/// `cowprotocol` consumers get a working client on either target without
/// naming a transport.
pub type DefaultTransport = FetchTransport;
/// HTTP method for an orderbook request. Kept minimal: the orderbook only
/// uses these four verbs.
/// A fully-formed, transport-agnostic request the orderbook client hands to
/// an [`HttpTransport`]. The body, when present, is already serialised JSON
/// and implies a `content-type: application/json` header.
/// Manual `Debug` impl that renders `bearer` as `Some("<redacted>")` so a
/// logging transport cannot leak the credential.
/// The response an [`HttpTransport`] returns after applying the body-size
/// cap. The body is decoded UTF-8 text; status handling and JSON decoding
/// happen in [`OrderBookApi`](crate::OrderBookApi) via the `decode_*`
/// helpers so both transports share one path.
/// HTTP backend [`OrderBookApi`](crate::OrderBookApi) issues requests
/// through. The `http-client` feature ships one implementation per build
/// target (see [`DefaultTransport`]): `ReqwestTransport` natively and the
/// browser-`fetch`-backed `FetchTransport` on wasm32.
///
/// The method is `async fn` rather than `-> impl Future + Send` on purpose:
/// the wasm `fetch` transport's future is `!Send`, so requiring `Send`
/// would make the trait unimplementable there. Native callers drive it with
/// a direct `.await` (no `tokio::spawn`), so the missing `Send` bound is not
/// a limitation in practice.
///
/// # Implementing a custom backend
///
/// The trait is feature-independent, so out-of-tree backends can
/// implement it without enabling `http-client`. A backend provides one
/// `async fn execute`, returning an [`HttpResponse`] whose `body` is the
/// decoded UTF-8 text (status handling and JSON decoding happen in
/// [`OrderBookApi`](crate::OrderBookApi)). This logging wrapper forwards
/// to an inner transport, then hands the result back unchanged:
///
/// ```
/// use cowprotocol_orderbook::error::Result;
/// use cowprotocol_orderbook::{HttpRequest, HttpResponse, HttpTransport};
///
/// struct Logged<T>(T);
///
/// impl<T: HttpTransport> HttpTransport for Logged<T> {
/// async fn execute(&self, request: HttpRequest) -> Result<HttpResponse> {
/// eprintln!("{:?} {}", request.method, request.url);
/// self.0.execute(request).await
/// }
/// }
/// ```
///
/// Pass an instance to
/// [`OrderBookApi::new_with_transport`](crate::OrderBookApi::new_with_transport).