Skip to main content

brainwires_proxy/middleware/
inspector.rs

1//! Traffic capture middleware — feeds events to the inspector subsystem.
2
3use crate::error::ProxyResult;
4use crate::inspector::{
5    EventBroadcaster, EventDirection, EventStore, TrafficEvent, TrafficEventKind,
6};
7use crate::middleware::{LayerAction, ProxyLayer};
8use crate::types::{ProxyRequest, ProxyResponse};
9use std::sync::Arc;
10
11/// Middleware that captures traffic events and publishes them to the
12/// inspector's store and broadcast channel.
13pub struct InspectorLayer {
14    store: Arc<EventStore>,
15    broadcaster: Arc<EventBroadcaster>,
16}
17
18impl InspectorLayer {
19    pub fn new(store: Arc<EventStore>, broadcaster: Arc<EventBroadcaster>) -> Self {
20        Self { store, broadcaster }
21    }
22}
23
24#[async_trait::async_trait]
25impl ProxyLayer for InspectorLayer {
26    async fn on_request(&self, request: ProxyRequest) -> ProxyResult<LayerAction> {
27        let event = TrafficEvent {
28            id: uuid::Uuid::new_v4(),
29            request_id: request.id.clone(),
30            timestamp: chrono::Utc::now(),
31            direction: EventDirection::Inbound,
32            kind: TrafficEventKind::Request {
33                method: request.method.to_string(),
34                uri: request.uri.to_string(),
35                headers: crate::inspector::headers_to_map(&request.headers),
36                body_size: request.body.len(),
37            },
38        };
39
40        self.store.push(event.clone());
41        let _ = self.broadcaster.send(event);
42
43        Ok(LayerAction::Forward(request))
44    }
45
46    async fn on_response(&self, response: ProxyResponse) -> ProxyResult<ProxyResponse> {
47        let event = TrafficEvent {
48            id: uuid::Uuid::new_v4(),
49            request_id: response.id.clone(),
50            timestamp: chrono::Utc::now(),
51            direction: EventDirection::Outbound,
52            kind: TrafficEventKind::Response {
53                status: response.status.as_u16(),
54                headers: crate::inspector::headers_to_map(&response.headers),
55                body_size: response.body.len(),
56            },
57        };
58
59        self.store.push(event.clone());
60        let _ = self.broadcaster.send(event);
61
62        Ok(response)
63    }
64
65    fn name(&self) -> &str {
66        "inspector"
67    }
68}