v0.25.1
This commit is contained in:
1 parent
87e571c170
commit
fa7abc9e53
308 files changed
+49746
-50237
No files matched your search
+11
-139
@@ -59,22 +59,13 @@ pub struct Exchange {
|
||||
impl Exchange {
|
||||
pub fn websocket_phase(&self, phase: &'static str) {
|
||||
if self.websocket_bootstrap.is_some() {
|
||||
*self
|
||||
.websocket_phase
|
||||
.lock()
|
||||
.unwrap_or_else(|e| e.into_inner()) = Some(phase);
|
||||
*self.websocket_phase.lock().unwrap_or_else(|e| e.into_inner()) = Some(phase);
|
||||
}
|
||||
}
|
||||
pub fn websocket_error(&self, phase: &'static str, error: &'static str) {
|
||||
if self.websocket_bootstrap.is_some() {
|
||||
*self
|
||||
.websocket_phase
|
||||
.lock()
|
||||
.unwrap_or_else(|e| e.into_inner()) = Some(phase);
|
||||
*self
|
||||
.websocket_error
|
||||
.lock()
|
||||
.unwrap_or_else(|e| e.into_inner()) = Some(error);
|
||||
*self.websocket_phase.lock().unwrap_or_else(|e| e.into_inner()) = Some(phase);
|
||||
*self.websocket_error.lock().unwrap_or_else(|e| e.into_inner()) = Some(error);
|
||||
}
|
||||
}
|
||||
pub fn h3_reset(&self, code: &'static str) {
|
||||
@@ -138,29 +129,12 @@ impl Drop for Exchange {
|
||||
.unwrap_or_else(|e| e.into_inner())
|
||||
.as_ref()
|
||||
.map(|l| l.member.backend.id.clone());
|
||||
let websocket_phase = *self
|
||||
.websocket_phase
|
||||
.lock()
|
||||
.unwrap_or_else(|e| e.into_inner());
|
||||
let websocket_phase = *self.websocket_phase.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let route = self.route.lock().unwrap_or_else(|e| e.into_inner()).clone();
|
||||
let cache_effective_enabled = *self
|
||||
.cache_effective_enabled
|
||||
.lock()
|
||||
.unwrap_or_else(|e| e.into_inner());
|
||||
let transform_effective_enabled = *self
|
||||
.transform_effective_enabled
|
||||
.lock()
|
||||
.unwrap_or_else(|e| e.into_inner());
|
||||
let client_ip = self
|
||||
.client_ip
|
||||
.lock()
|
||||
.unwrap_or_else(|e| e.into_inner())
|
||||
.clone();
|
||||
let country = self
|
||||
.country
|
||||
.lock()
|
||||
.unwrap_or_else(|e| e.into_inner())
|
||||
.clone();
|
||||
let cache_effective_enabled = *self.cache_effective_enabled.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let transform_effective_enabled = *self.transform_effective_enabled.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let client_ip = self.client_ip.lock().unwrap_or_else(|e| e.into_inner()).clone();
|
||||
let country = self.country.lock().unwrap_or_else(|e| e.into_inner()).clone();
|
||||
let request_bytes = self.request_bytes.load(Ordering::Relaxed);
|
||||
let response_bytes = self.response_bytes.load(Ordering::Relaxed);
|
||||
let duration_ms = duration.as_millis() as u64;
|
||||
@@ -213,20 +187,13 @@ impl Drop for Exchange {
|
||||
transport: self.transport,
|
||||
websocket_bootstrap: self.websocket_bootstrap,
|
||||
websocket_phase,
|
||||
websocket_error: *self
|
||||
.websocket_error
|
||||
.lock()
|
||||
.unwrap_or_else(|e| e.into_inner()),
|
||||
websocket_error: *self.websocket_error.lock().unwrap_or_else(|e| e.into_inner()),
|
||||
h3_reset_code: *self.h3_reset_code.lock().unwrap_or_else(|e| e.into_inner()),
|
||||
upstream_status: match self.upstream_status.load(Ordering::Relaxed) {
|
||||
0 => None,
|
||||
value => Some(value),
|
||||
},
|
||||
upstream_error: self
|
||||
.upstream_error
|
||||
.lock()
|
||||
.unwrap_or_else(|e| e.into_inner())
|
||||
.clone(),
|
||||
upstream_error: self.upstream_error.lock().unwrap_or_else(|e| e.into_inner()).clone(),
|
||||
client_ip,
|
||||
user_agent: self.user_agent.clone(),
|
||||
country,
|
||||
@@ -367,102 +334,7 @@ impl Drop for MeteredBody {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use http_body_util::BodyExt;
|
||||
use tokio::sync::Semaphore;
|
||||
async fn observation() -> (Arc<Exchange>, Arc<Semaphore>) {
|
||||
let slots = Arc::new(Semaphore::new(1));
|
||||
let permit = slots.clone().acquire_owned().await.unwrap();
|
||||
let metrics = Arc::new(Metrics::default());
|
||||
metrics.active.store(1, Ordering::Relaxed);
|
||||
let exchange = Arc::new(Exchange {
|
||||
vhost_metrics: None,
|
||||
vhost: None,
|
||||
route: Mutex::new(None),
|
||||
cache_effective_enabled: Mutex::new(None),
|
||||
transform_effective_enabled: Mutex::new(None),
|
||||
backend: Mutex::new(None),
|
||||
id: 1,
|
||||
method: "POST".into(),
|
||||
host: "localhost".into(),
|
||||
path: "/echo".into(),
|
||||
http_version: "1.1",
|
||||
transport: "h1",
|
||||
websocket_bootstrap: None,
|
||||
websocket_phase: Mutex::new(None),
|
||||
websocket_error: Mutex::new(None),
|
||||
h3_reset_code: Mutex::new(None),
|
||||
upstream_status: AtomicU16::new(0),
|
||||
upstream_error: Mutex::new(None),
|
||||
client_ip: Mutex::new(Some("127.0.0.1".into())),
|
||||
user_agent: Some("RustProxy-Test/1.0".into()),
|
||||
country: Mutex::new(Some("PL".into())),
|
||||
started: Instant::now(),
|
||||
status: AtomicU16::new(200),
|
||||
cache_status: AtomicU16::new(0),
|
||||
cache_reason: Mutex::new("not_proxy_response"),
|
||||
failed: AtomicBool::new(false),
|
||||
aborted: AtomicBool::new(false),
|
||||
request_bytes: AtomicU64::new(0),
|
||||
response_bytes: AtomicU64::new(0),
|
||||
metrics,
|
||||
logs: Arc::new(Logs::default()),
|
||||
traffic: crate::traffic::Analytics::start(tokio_util::sync::CancellationToken::new()),
|
||||
_permit: permit,
|
||||
});
|
||||
(exchange, slots)
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn permit_and_metrics_cover_both_bodies() {
|
||||
let (exchange, slots) = observation().await;
|
||||
let metrics = exchange.metrics.clone();
|
||||
let logs = exchange.logs.clone();
|
||||
let input = MeteredBody::new(
|
||||
Body::from("in"),
|
||||
exchange.clone(),
|
||||
Direction::Request,
|
||||
Duration::from_secs(1),
|
||||
);
|
||||
let output = MeteredBody::new(
|
||||
Body::from("out"),
|
||||
exchange.clone(),
|
||||
Direction::Response,
|
||||
Duration::from_secs(1),
|
||||
);
|
||||
drop(exchange);
|
||||
assert_eq!(
|
||||
input.collect().await.unwrap().to_bytes(),
|
||||
Bytes::from_static(b"in")
|
||||
);
|
||||
assert_eq!(slots.available_permits(), 0);
|
||||
assert_eq!(
|
||||
output.collect().await.unwrap().to_bytes(),
|
||||
Bytes::from_static(b"out")
|
||||
);
|
||||
assert_eq!(slots.available_permits(), 1);
|
||||
assert_eq!(metrics.active.load(Ordering::Relaxed), 0);
|
||||
assert_eq!(metrics.bytes_in.load(Ordering::Relaxed), 2);
|
||||
assert_eq!(metrics.bytes_out.load(Ordering::Relaxed), 3);
|
||||
assert_eq!(metrics.completed.load(Ordering::Relaxed), 1);
|
||||
assert_eq!(logs.recent().len(), 1);
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn idle_body_fails_and_releases_capacity() {
|
||||
let (exchange, slots) = observation().await;
|
||||
let metrics = exchange.metrics.clone();
|
||||
let pending = futures_util::stream::pending::<Result<Bytes, std::io::Error>>();
|
||||
let output = MeteredBody::new(
|
||||
Body::from_stream(pending),
|
||||
exchange,
|
||||
Direction::Response,
|
||||
Duration::from_millis(10),
|
||||
);
|
||||
assert!(output.collect().await.is_err());
|
||||
assert_eq!(slots.available_permits(), 1);
|
||||
assert_eq!(metrics.errors.load(Ordering::Relaxed), 1);
|
||||
}
|
||||
}
|
||||
include!("body/tests.rs");
|
||||
|
||||
/// Retains the first inspected frame without collecting the rest of a request.
|
||||
/// A trailer/empty DATA frame still prevents storing a request-body variant.
|
||||
|
||||
Reference in new issue
Block a user