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
//! Middleware that detects when a response future or response body is
//! dropped before completion.
//!
//! HTTP services typically learn nothing when a client disconnects
//! mid-request. This middleware installs drop guards so that premature
//! termination is observable: logs, metrics, cleanup.
//!
//! Two events are distinguished:
//!
//! * **Future drop**: the response future was dropped before the inner
//! service produced any response.
//! * **Body drop**: the response body was dropped before reaching
//! [`is_end_stream`](http_body::Body::is_end_stream).
//!
//! # Example: bridge to [`trace::OnFailure`](crate::trace::OnFailure)
//!
//! With the `trace` feature, [`EarlyDropsAsFailures`] wraps any
//! [`OnFailure<DroppedFailure>`](crate::trace::OnFailure) and routes both
//! events through it. Place this layer inside [`TraceLayer`](crate::trace::TraceLayer)
//! so that the emitted events inherit the request span.
//!
//! ```
//! # #[cfg(feature = "trace")] {
//! use tower_http::on_early_drop::{OnEarlyDropLayer, EarlyDropsAsFailures};
//! use tower_http::trace::DefaultOnFailure;
//!
//! let layer = OnEarlyDropLayer::new(
//! EarlyDropsAsFailures::new(DefaultOnFailure::default()),
//! );
//! # }
//! ```
//!
//! Use [`OnEarlyDropLayer::builder`] to place [`EarlyDropsAsFailures`] in a
//! single slot (track only body or only future drops) or to install plain
//! closures.
//!
//! # Example: builder with direct callbacks
//!
//! Use [`OnEarlyDropLayer::builder`] to install closures in either or both
//! slots. The future-drop closure is a factory: outer closure runs at
//! request time, inner closure fires on drop. The body-drop closure uses a
//! three-level chain via [`OnBodyDropFn`]: outer at request time, middle at
//! response-ready time, inner on drop.
//!
//! ```
//! use http::Request;
//! use tower_http::on_early_drop::{OnBodyDropFn, OnEarlyDropLayer};
//!
//! let layer = OnEarlyDropLayer::builder()
//! .on_future_drop(|req: &Request<()>| {
//! let uri = req.uri().clone();
//! move || eprintln!("future dropped for {}", uri)
//! })
//! .on_body_drop(OnBodyDropFn::new(|req: &Request<()>| {
//! let uri = req.uri().clone();
//! move |parts: &http::response::Parts| {
//! let status = parts.status;
//! move || eprintln!("body dropped for {} status {}", uri, status)
//! }
//! }));
//! ```
//!
//! Chain just one of the two methods to hook only that event; the other
//! slot stays no-op.
//!
//! # Panics in callbacks
//!
//! Callbacks fire from [`Drop`]. Panicking during a drop that occurs while
//! another panic is unwinding aborts the process. Closures and custom
//! [`OnDropCallback`] implementations must not panic.
//!
//! # Standalone guard
//!
//! [`OnEarlyDropGuard`] is usable on its own to detect early drop of
//! arbitrary scopes.
//!
//! ```
//! use tower_http::on_early_drop::OnEarlyDropGuard;
//!
//! let mut guard = OnEarlyDropGuard::new(|| {
//! eprintln!("scope exited early");
//! });
//! // ... work that might return early ...
//! guard.completed();
//! ```
pub use ;
pub use ;