slinger_mitm/
interceptor.rs1use crate::error::Result;
4use slinger::{Request, Response};
5use std::sync::Arc;
6
7#[async_trait::async_trait]
9pub trait RequestInterceptor: Send + Sync {
10 async fn intercept_request(&self, request: Request) -> Result<Option<Request>>;
14}
15
16#[async_trait::async_trait]
18pub trait ResponseInterceptor: Send + Sync {
19 async fn intercept_response(&self, response: Response) -> Result<Option<Response>>;
23}
24
25pub struct InterceptorHandler {
27 request_interceptors: Vec<Arc<dyn RequestInterceptor>>,
28 response_interceptors: Vec<Arc<dyn ResponseInterceptor>>,
29}
30
31impl InterceptorHandler {
32 pub fn new() -> Self {
34 Self {
35 request_interceptors: Vec::new(),
36 response_interceptors: Vec::new(),
37 }
38 }
39
40 pub fn add_request_interceptor(&mut self, interceptor: Arc<dyn RequestInterceptor>) {
42 self.request_interceptors.push(interceptor);
43 }
44
45 pub fn add_response_interceptor(&mut self, interceptor: Arc<dyn ResponseInterceptor>) {
47 self.response_interceptors.push(interceptor);
48 }
49
50 pub async fn process_request(&self, mut request: Request) -> Result<Option<Request>> {
52 for interceptor in &self.request_interceptors {
53 match interceptor.intercept_request(request).await? {
54 Some(modified) => request = modified,
55 None => return Ok(None), }
57 }
58 Ok(Some(request))
59 }
60
61 pub async fn process_response(&self, mut response: Response) -> Result<Option<Response>> {
63 for interceptor in &self.response_interceptors {
64 match interceptor.intercept_response(response).await? {
65 Some(modified) => response = modified,
66 None => return Ok(None), }
68 }
69 Ok(Some(response))
70 }
71}
72
73impl Default for InterceptorHandler {
74 fn default() -> Self {
75 Self::new()
76 }
77}
78
79pub struct Interceptor;
81
82impl Interceptor {
83 pub fn logging() -> LoggingInterceptor {
85 LoggingInterceptor
86 }
87}
88
89pub struct LoggingInterceptor;
91
92#[async_trait::async_trait]
93impl RequestInterceptor for LoggingInterceptor {
94 async fn intercept_request(&self, request: Request) -> Result<Option<Request>> {
95 tracing::info!("[MITM] Request: {} {}", request.method(), request.uri());
96 for (name, value) in request.headers() {
97 tracing::info!(" {}: {:?}", name, value);
98 }
99 Ok(Some(request))
100 }
101}
102
103#[async_trait::async_trait]
104impl ResponseInterceptor for LoggingInterceptor {
105 async fn intercept_response(&self, response: Response) -> Result<Option<Response>> {
106 tracing::info!("[MITM] Response: {}", response.status_code());
107 for (name, value) in response.headers() {
108 tracing::info!(" {}: {:?}", name, value);
109 }
110 Ok(Some(response))
112 }
113}