diff --git a/mitm_proxy/src/mitm_proxy.rs b/mitm_proxy/src/mitm_proxy.rs index 30584eb..84d9ba0 100644 --- a/mitm_proxy/src/mitm_proxy.rs +++ b/mitm_proxy/src/mitm_proxy.rs @@ -1,4 +1,4 @@ -use std::sync::mpsc::Receiver; +use std::{sync::mpsc::Receiver, fmt::{Display, format}, default}; use crate::{ requests::{InfoOptions, RequestInfo}, @@ -8,13 +8,13 @@ use crate::{ use eframe::{ egui::{ self, FontData, FontDefinitions, FontFamily, Grid, Layout, ScrollArea, Style, TextStyle::*, - TopBottomPanel, Visuals, + TopBottomPanel, Visuals, RichText, ComboBox, }, epaint::FontId, Frame, }; use egui_extras::{Column, TableBuilder}; -use proxyapi::*; +use proxyapi::{*, hyper::Method}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] @@ -40,8 +40,41 @@ impl Default for MitmProxyConfig { } } + +#[derive(Debug,Default,PartialEq, Eq)] +pub enum MethodFilter { + #[default] + All, + Only(Method), +} +impl MethodFilter{ + const METHODS: [(&'static str,Self);10]=[ + ("All",MethodFilter::All), + ("GET",MethodFilter::Only(Method::GET)), + ("POST",MethodFilter::Only(Method::POST)), + ("PUT",MethodFilter::Only(Method::PUT)), + ("DELETE",MethodFilter::Only(Method::DELETE)), + ("PATCH",MethodFilter::Only(Method::PATCH)), + ("HEAD",MethodFilter::Only(Method::HEAD)), + ("OPTIONS",MethodFilter::Only(Method::OPTIONS)), + ("CONNECT",MethodFilter::Only(Method::CONNECT)), + ("TRACE",MethodFilter::Only(Method::TRACE)), + ]; +} +impl Display for MethodFilter { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Self::Only(method) = self { + Display::fmt(method, f) + }else { + f.write_str("All") + } + } +} + + struct MitmProxyState { selected_request: Option, + selected_request_method: MethodFilter, detail_option: InfoOptions, } @@ -49,6 +82,7 @@ impl MitmProxyState { fn new() -> Self { Self { selected_request: None, + selected_request_method: MethodFilter::All, detail_option: InfoOptions::Request, } } @@ -155,18 +189,31 @@ impl MitmProxy { header.col(|_ui| ()); }) - .body(|body| { - body.rows(text_height, self.requests.len(), |row_index, mut row| { - self.requests - .get_mut(row_index) - .expect("Problem with index") - .render_row(&mut row); - row.col(|ui| { - if ui.button("🔎").clicked() { - self.state.selected_request = Some(row_index); - } - }); - }) + .body(|mut body| { + if let MethodFilter::Only(filter_method) = &self.state.selected_request_method { + for (row_index, request) in self.requests.iter().enumerate().filter(|r|r.1.should_show(&filter_method)) { + body.row(text_height, |mut row|{ + request.render_row(&mut row); + row.col(|ui| { + if ui.button("🔎").clicked() { + self.state.selected_request = Some(row_index); + } + }); + }); + } + }else{ + body.rows(text_height, self.requests.len(), |row_index, mut row| { + self.requests + .get_mut(row_index) + .expect("Problem with index") + .render_row(&mut row); + row.col(|ui| { + if ui.button("🔎").clicked() { + self.state.selected_request = Some(row_index); + } + }); + }) + } }); } @@ -247,6 +294,23 @@ impl MitmProxy { }) .on_hover_text("Toggle theme"); + + + const COMBOBOX_TEXT_SIZE:f32=15.; + ComboBox::from_label("") + .selected_text(RichText::new(format!("{} Requests",&self.state.selected_request_method)).size(COMBOBOX_TEXT_SIZE)) + .wrap(false) + .show_ui(ui, |ui| { + ui.style_mut().wrap = Some(false); + for (method_str, method) in MethodFilter::METHODS { + ui.selectable_value( + &mut self.state.selected_request_method, + method, + RichText::new(method_str).size(COMBOBOX_TEXT_SIZE) + ); + } + }); + if close_btn.clicked() { frame.close(); } diff --git a/mitm_proxy/src/requests.rs b/mitm_proxy/src/requests.rs index 5b9bf17..a081192 100644 --- a/mitm_proxy/src/requests.rs +++ b/mitm_proxy/src/requests.rs @@ -2,9 +2,10 @@ use std::collections::HashMap; use eframe::egui::{self}; use egui_extras::TableRow; -use proxyapi::*; +use proxyapi::{*, hyper::Method}; struct Request { + http_method: Method, method: String, uri: String, version: String, @@ -15,6 +16,7 @@ struct Request { impl Request { fn new( + http_method: Method, method: String, uri: String, version: String, @@ -23,6 +25,7 @@ impl Request { time: i64, ) -> Self { Self { + http_method, method, uri, version, @@ -93,6 +96,7 @@ impl From for RequestInfo { fn from(value: Output) -> Self { let request = match value.req() { Some(r) => Some(Request::new( + r.http_method().clone(), r.method().to_string(), r.uri().to_string(), r.version().to_string(), @@ -180,6 +184,14 @@ impl RequestInfo { } } + pub fn should_show(&self, method:&Method)->bool { + if let Some(req) = &self.request { + req.http_method == method + }else{ + false + } + } + pub fn show_details(&mut self, ui: &mut egui::Ui) { ui.label(match &self.details { Some(_) => "Some details", @@ -187,7 +199,7 @@ impl RequestInfo { }); } - pub fn render_row(&mut self, row: &mut TableRow) { + pub fn render_row(&self, row: &mut TableRow) { let req = self.request.as_ref().unwrap(); let res = self.response.as_ref().unwrap(); let time = (res.time as f64 - req.time as f64) * 10_f64.powf(-9.0) as f64; diff --git a/proxyapi/src/output.rs b/proxyapi/src/output.rs index 641d552..055874e 100644 --- a/proxyapi/src/output.rs +++ b/proxyapi/src/output.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, sync::mpsc::SyncSender}; use async_trait::async_trait; -use http::{HeaderMap, Version, Response, Request}; +use http::{HeaderMap, Version, Response, Request, Method}; use hyper::{Body}; use crate::{HttpHandler, HttpContext, RequestResponse}; @@ -55,6 +55,7 @@ impl HttpHandler for Output { async fn handle_request(&mut self, _ctx: &HttpContext, req: Request, ) -> RequestResponse { println!("request{:?}\n", req); let output_request = OutputRequest::new( + req.method().clone(), req.method().to_string(), req.uri().to_string(), req.version().to_string(), @@ -91,6 +92,7 @@ impl HttpHandler for Output { #[derive(Clone, Debug)] pub struct OutputRequest { + http_method: Method, method: String, uri: String, version: String, @@ -101,6 +103,7 @@ pub struct OutputRequest { impl OutputRequest { fn new( + http_method: Method, method: String, uri: String, version: String, @@ -109,6 +112,7 @@ impl OutputRequest { time: i64, ) -> Self { Self { + http_method, method, uri, version, @@ -118,6 +122,10 @@ impl OutputRequest { } } + pub fn http_method(&self) -> &Method { + &self.http_method + } + pub fn method(&self) -> &String { &self.method }