1pub use self::internal::builder;
40
41#[cfg(docsrs)]
42pub use self::internal::Builder;
43#[cfg(docsrs)]
44pub use self::internal::Negotiate;
45#[cfg(docsrs)]
46pub use self::internal::Negotiated;
47
48mod internal {
49 use std::pin::Pin;
50 use std::sync::{Arc, Mutex};
51 use std::task::{self, Poll, ready};
52
53 use pin_project_lite::pin_project;
54 use tower_layer::Layer;
55 use tower_service::Service;
56
57 type BoxError = Box<dyn std::error::Error + Send + Sync>;
58
59 #[derive(Clone)]
69 pub struct Negotiate<L, R> {
70 left: L,
71 right: R,
72 }
73
74 #[derive(Clone, Debug)]
82 pub enum Negotiated<L, R> {
83 #[doc(hidden)]
84 Fallback(L),
85 #[doc(hidden)]
86 Upgraded(R),
87 }
88
89 pin_project! {
90 pub struct Negotiating<Dst, L, R>
91 where
92 L: Service<Dst>,
93 R: Service<()>,
94 {
95 #[pin]
96 state: State<Dst, L::Future, R::Future>,
97 left: L,
98 right: R,
99 }
100 }
101
102 pin_project! {
103 #[project = StateProj]
104 enum State<Dst, FL, FR> {
105 Eager {
106 #[pin]
107 future: FR,
108 dst: Option<Dst>,
109 },
110 Fallback {
111 #[pin]
112 future: FL,
113 },
114 Upgrade {
115 #[pin]
116 future: FR,
117 }
118 }
119 }
120
121 pin_project! {
122 #[project = NegotiatedProj]
123 pub enum NegotiatedFuture<L, R> {
124 Fallback {
125 #[pin]
126 future: L
127 },
128 Upgraded {
129 #[pin]
130 future: R
131 },
132 }
133 }
134
135 #[derive(Debug)]
143 pub struct Builder<C, I, L, R> {
144 connect: C,
145 inspect: I,
146 fallback: L,
147 upgrade: R,
148 }
149
150 #[derive(Debug)]
151 pub struct WantsConnect;
152 #[derive(Debug)]
153 pub struct WantsInspect;
154 #[derive(Debug)]
155 pub struct WantsFallback;
156 #[derive(Debug)]
157 pub struct WantsUpgrade;
158
159 pub fn builder() -> Builder<WantsConnect, WantsInspect, WantsFallback, WantsUpgrade> {
161 Builder {
162 connect: WantsConnect,
163 inspect: WantsInspect,
164 fallback: WantsFallback,
165 upgrade: WantsUpgrade,
166 }
167 }
168
169 impl<C, I, L, R> Builder<C, I, L, R> {
170 pub fn connect<CC>(self, connect: CC) -> Builder<CC, I, L, R> {
172 Builder {
173 connect,
174 inspect: self.inspect,
175 fallback: self.fallback,
176 upgrade: self.upgrade,
177 }
178 }
179
180 pub fn inspect<II>(self, inspect: II) -> Builder<C, II, L, R> {
182 Builder {
183 connect: self.connect,
184 inspect,
185 fallback: self.fallback,
186 upgrade: self.upgrade,
187 }
188 }
189
190 pub fn fallback<LL>(self, fallback: LL) -> Builder<C, I, LL, R> {
192 Builder {
193 connect: self.connect,
194 inspect: self.inspect,
195 fallback,
196 upgrade: self.upgrade,
197 }
198 }
199
200 pub fn upgrade<RR>(self, upgrade: RR) -> Builder<C, I, L, RR> {
202 Builder {
203 connect: self.connect,
204 inspect: self.inspect,
205 fallback: self.fallback,
206 upgrade,
207 }
208 }
209
210 pub fn build<Dst>(self) -> Negotiate<L::Service, R::Service>
212 where
213 C: Service<Dst>,
214 C::Error: Into<BoxError>,
215 L: Layer<Inspector<C, C::Response, I>>,
216 L::Service: Service<Dst> + Clone,
217 <L::Service as Service<Dst>>::Error: Into<BoxError>,
218 R: Layer<Inspected<C::Response>>,
219 R::Service: Service<()> + Clone,
220 <R::Service as Service<()>>::Error: Into<BoxError>,
221 I: Fn(&C::Response) -> bool + Clone,
222 {
223 let Builder {
224 connect,
225 inspect,
226 fallback,
227 upgrade,
228 } = self;
229
230 let slot = Arc::new(Mutex::new(None));
231 let wrapped = Inspector {
232 svc: connect,
233 inspect,
234 slot: slot.clone(),
235 };
236 let left = fallback.layer(wrapped);
237
238 let right = upgrade.layer(Inspected { slot });
239
240 Negotiate { left, right }
241 }
242 }
243
244 impl<L, R> Negotiate<L, R> {
245 pub fn fallback_mut(&mut self) -> &mut L {
247 &mut self.left
248 }
249
250 pub fn upgrade_mut(&mut self) -> &mut R {
252 &mut self.right
253 }
254 }
255
256 impl<L, R, Target> Service<Target> for Negotiate<L, R>
257 where
258 L: Service<Target> + Clone,
259 L::Error: Into<BoxError>,
260 R: Service<()> + Clone,
261 R::Error: Into<BoxError>,
262 {
263 type Response = Negotiated<L::Response, R::Response>;
264 type Error = BoxError;
265 type Future = Negotiating<Target, L, R>;
266
267 fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
268 self.left.poll_ready(cx).map_err(Into::into)
269 }
270
271 fn call(&mut self, dst: Target) -> Self::Future {
272 let left = self.left.clone();
273 Negotiating {
274 state: State::Eager {
275 future: self.right.call(()),
276 dst: Some(dst),
277 },
278 left: std::mem::replace(&mut self.left, left),
280 right: self.right.clone(),
281 }
282 }
283 }
284
285 impl<Dst, L, R> Future for Negotiating<Dst, L, R>
286 where
287 L: Service<Dst>,
288 L::Error: Into<BoxError>,
289 R: Service<()>,
290 R::Error: Into<BoxError>,
291 {
292 type Output = Result<Negotiated<L::Response, R::Response>, BoxError>;
293
294 fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
295 let mut me = self.project();
301 loop {
302 match me.state.as_mut().project() {
303 StateProj::Eager { future, dst } => match ready!(future.poll(cx)) {
304 Ok(out) => return Poll::Ready(Ok(Negotiated::Upgraded(out))),
305 Err(err) => {
306 let err = err.into();
307 if UseOther::is(&*err) {
308 let dst = dst.take().unwrap();
309 let f = me.left.call(dst);
310 me.state.set(State::Fallback { future: f });
311 continue;
312 } else {
313 return Poll::Ready(Err(err));
314 }
315 }
316 },
317 StateProj::Fallback { future } => match ready!(future.poll(cx)) {
318 Ok(out) => return Poll::Ready(Ok(Negotiated::Fallback(out))),
319 Err(err) => {
320 let err = err.into();
321 if UseOther::is(&*err) {
322 let f = me.right.call(());
323 me.state.set(State::Upgrade { future: f });
324 continue;
325 } else {
326 return Poll::Ready(Err(err));
327 }
328 }
329 },
330 StateProj::Upgrade { future } => match ready!(future.poll(cx)) {
331 Ok(out) => return Poll::Ready(Ok(Negotiated::Upgraded(out))),
332 Err(err) => return Poll::Ready(Err(err.into())),
333 },
334 }
335 }
336 }
337 }
338
339 impl<L, R> Negotiated<L, R> {
340 #[cfg(test)]
342 pub(super) fn is_fallback(&self) -> bool {
343 matches!(self, Negotiated::Fallback(_))
344 }
345
346 #[cfg(test)]
347 pub(super) fn is_upgraded(&self) -> bool {
348 matches!(self, Negotiated::Upgraded(_))
349 }
350
351 pub fn fallback_ref(&self) -> Option<&L> {
355 if let Negotiated::Fallback(left) = self {
356 Some(left)
357 } else {
358 None
359 }
360 }
361
362 pub fn fallback_mut(&mut self) -> Option<&mut L> {
364 if let Negotiated::Fallback(left) = self {
365 Some(left)
366 } else {
367 None
368 }
369 }
370
371 pub fn upgraded_ref(&self) -> Option<&R> {
373 if let Negotiated::Upgraded(right) = self {
374 Some(right)
375 } else {
376 None
377 }
378 }
379
380 pub fn upgraded_mut(&mut self) -> Option<&mut R> {
382 if let Negotiated::Upgraded(right) = self {
383 Some(right)
384 } else {
385 None
386 }
387 }
388 }
389
390 impl<L, R, Req, Res, E> Service<Req> for Negotiated<L, R>
391 where
392 L: Service<Req, Response = Res, Error = E>,
393 R: Service<Req, Response = Res, Error = E>,
394 {
395 type Response = Res;
396 type Error = E;
397 type Future = NegotiatedFuture<L::Future, R::Future>;
398
399 fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
400 match self {
401 Negotiated::Fallback(s) => s.poll_ready(cx),
402 Negotiated::Upgraded(s) => s.poll_ready(cx),
403 }
404 }
405
406 fn call(&mut self, req: Req) -> Self::Future {
407 match self {
408 Negotiated::Fallback(s) => NegotiatedFuture::Fallback {
409 future: s.call(req),
410 },
411 Negotiated::Upgraded(s) => NegotiatedFuture::Upgraded {
412 future: s.call(req),
413 },
414 }
415 }
416 }
417
418 impl<L, R, Out> Future for NegotiatedFuture<L, R>
419 where
420 L: Future<Output = Out>,
421 R: Future<Output = Out>,
422 {
423 type Output = Out;
424
425 fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
426 match self.project() {
427 NegotiatedProj::Fallback { future } => future.poll(cx),
428 NegotiatedProj::Upgraded { future } => future.poll(cx),
429 }
430 }
431 }
432
433 pub struct Inspector<M, S, I> {
436 svc: M,
437 inspect: I,
438 slot: Arc<Mutex<Option<S>>>,
439 }
440
441 pin_project! {
442 pub struct InspectFuture<F, S, I> {
443 #[pin]
444 future: F,
445 inspect: I,
446 slot: Arc<Mutex<Option<S>>>,
447 }
448 }
449
450 impl<M: Clone, S, I: Clone> Clone for Inspector<M, S, I> {
451 fn clone(&self) -> Self {
452 Self {
453 svc: self.svc.clone(),
454 inspect: self.inspect.clone(),
455 slot: self.slot.clone(),
456 }
457 }
458 }
459
460 impl<M, S, I, Target> Service<Target> for Inspector<M, S, I>
461 where
462 M: Service<Target, Response = S>,
463 M::Error: Into<BoxError>,
464 I: Clone + Fn(&S) -> bool,
465 {
466 type Response = M::Response;
467 type Error = BoxError;
468 type Future = InspectFuture<M::Future, S, I>;
469
470 fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
471 self.svc.poll_ready(cx).map_err(Into::into)
472 }
473
474 fn call(&mut self, dst: Target) -> Self::Future {
475 InspectFuture {
476 future: self.svc.call(dst),
477 inspect: self.inspect.clone(),
478 slot: self.slot.clone(),
479 }
480 }
481 }
482
483 impl<F, I, S, E> Future for InspectFuture<F, S, I>
484 where
485 F: Future<Output = Result<S, E>>,
486 E: Into<BoxError>,
487 I: Fn(&S) -> bool,
488 {
489 type Output = Result<S, BoxError>;
490
491 fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
492 let me = self.project();
493 let s = ready!(me.future.poll(cx)).map_err(Into::into)?;
494 Poll::Ready(if (me.inspect)(&s) {
495 *me.slot.lock().unwrap() = Some(s);
496 Err(UseOther.into())
497 } else {
498 Ok(s)
499 })
500 }
501 }
502
503 pub struct Inspected<S> {
504 slot: Arc<Mutex<Option<S>>>,
505 }
506
507 impl<S, Target> Service<Target> for Inspected<S> {
508 type Response = S;
509 type Error = BoxError;
510 type Future = std::future::Ready<Result<S, BoxError>>;
511
512 fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
513 if self.slot.lock().unwrap().is_some() {
514 Poll::Ready(Ok(()))
515 } else {
516 Poll::Ready(Err(UseOther.into()))
517 }
518 }
519
520 fn call(&mut self, _dst: Target) -> Self::Future {
521 let s = self
522 .slot
523 .lock()
524 .unwrap()
525 .take()
526 .ok_or_else(|| UseOther.into());
527 std::future::ready(s)
528 }
529 }
530
531 impl<S> Clone for Inspected<S> {
532 fn clone(&self) -> Inspected<S> {
533 Inspected {
534 slot: self.slot.clone(),
535 }
536 }
537 }
538
539 #[derive(Debug)]
540 struct UseOther;
541
542 impl std::fmt::Display for UseOther {
543 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
544 f.write_str("sentinel error; using other")
545 }
546 }
547
548 impl std::error::Error for UseOther {}
549
550 impl UseOther {
551 fn is(err: &(dyn std::error::Error + 'static)) -> bool {
552 let mut source = Some(err);
553 while let Some(err) = source {
554 if err.is::<UseOther>() {
555 return true;
556 }
557 source = err.source();
558 }
559 false
560 }
561 }
562}
563
564#[cfg(test)]
565mod tests {
566 use futures_util::future;
567 use tower_service::Service;
568 use tower_test::assert_request_eq;
569
570 #[tokio::test]
571 async fn not_negotiated_falls_back_to_left() {
572 let (mock_svc, mut handle) = tower_test::mock::pair::<(), &'static str>();
573
574 let mut negotiate = super::builder()
575 .connect(mock_svc)
576 .inspect(|_: &&str| false)
577 .fallback(layer_fn(|s| s))
578 .upgrade(layer_fn(|s| s))
579 .build();
580
581 std::future::poll_fn(|cx| negotiate.poll_ready(cx))
582 .await
583 .unwrap();
584
585 let fut = negotiate.call(());
586 let nsvc = future::join(fut, async move {
587 assert_request_eq!(handle, ()).send_response("one");
588 })
589 .await
590 .0
591 .expect("call");
592 assert!(nsvc.is_fallback());
593 }
594
595 #[tokio::test]
596 async fn negotiated_uses_right() {
597 let (mock_svc, mut handle) = tower_test::mock::pair::<(), &'static str>();
598
599 let mut negotiate = super::builder()
600 .connect(mock_svc)
601 .inspect(|_: &&str| true)
602 .fallback(layer_fn(|s| s))
603 .upgrade(layer_fn(|s| s))
604 .build();
605
606 std::future::poll_fn(|cx| negotiate.poll_ready(cx))
607 .await
608 .unwrap();
609
610 let fut = negotiate.call(());
611 let nsvc = future::join(fut, async move {
612 assert_request_eq!(handle, ()).send_response("one");
613 })
614 .await
615 .0
616 .expect("call");
617
618 assert!(nsvc.is_upgraded());
619 }
620
621 fn layer_fn<F>(f: F) -> LayerFn<F> {
622 LayerFn(f)
623 }
624
625 #[derive(Clone)]
626 struct LayerFn<F>(F);
627
628 impl<F, S, Out> tower_layer::Layer<S> for LayerFn<F>
629 where
630 F: Fn(S) -> Out,
631 {
632 type Service = Out;
633 fn layer(&self, inner: S) -> Self::Service {
634 (self.0)(inner)
635 }
636 }
637}