Implement middleware function

This commit is contained in:
Martin Algesten
2021-12-20 10:21:19 +01:00
parent 7b2f28bbc2
commit 09ecb6ffd6
5 changed files with 290 additions and 10 deletions

67
examples/count-bytes.rs Normal file
View File

@@ -0,0 +1,67 @@
use std::sync::{Arc, Mutex};
use ureq::{Error, Middleware, MiddlewareNext, Request, Response};
// Some state that could be shared with the main application.
#[derive(Debug, Default)]
struct CounterState {
request_count: u64,
total_bytes: u64,
}
// Middleware wrapper working off the shared state.
struct CounterMiddleware(Arc<Mutex<CounterState>>);
pub fn main() -> Result<(), Error> {
// Shared state for counters.
let shared_state = Arc::new(Mutex::new(CounterState::default()));
let agent = ureq::builder()
// Clone the state into the middleware
.middleware(CounterMiddleware(shared_state.clone()))
.build();
agent.get("https://httpbin.org/bytes/123").call()?;
agent.get("https://httpbin.org/bytes/123").call()?;
{
let state = shared_state.lock().unwrap();
println!("State after requests:\n\n{:?}\n", state);
assert_eq!(state.request_count, 2);
assert_eq!(state.total_bytes, 246);
}
Ok(())
}
impl Middleware for CounterMiddleware {
fn handle(&self, request: Request, next: MiddlewareNext) -> Result<Response, Error> {
// Get state before request to increase request counter.
// Extra brackets to release the lock while continuing the chain.
{
let mut state = self.0.lock().unwrap();
state.request_count += 1;
} // release lock
// Continue the middleware chain
let response = next.handle(request)?;
// Get state after response to increase byte count.
// Extra brackets not necessary, but there for symmetry with first lock.
{
let mut state = self.0.lock().unwrap();
let len = response
.header("Content-Length")
.and_then(|s| s.parse::<u64>().ok())
.unwrap();
state.total_bytes += len;
} // release lock
Ok(response)
}
}