Skip to content

Commit 75c7c04

Browse files
authored
Merge pull request #19 from MMukundi/feature/method_filter
Implement filtering requests by method
2 parents 7a3b5b8 + d69792e commit 75c7c04

File tree

3 files changed

+102
-18
lines changed

3 files changed

+102
-18
lines changed

mitm_proxy/src/mitm_proxy.rs

Lines changed: 79 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::sync::mpsc::Receiver;
1+
use std::{sync::mpsc::Receiver, fmt::{Display, format}, default};
22

33
use crate::{
44
requests::{InfoOptions, RequestInfo},
@@ -8,13 +8,13 @@ use crate::{
88
use eframe::{
99
egui::{
1010
self, FontData, FontDefinitions, FontFamily, Grid, Layout, ScrollArea, Style, TextStyle::*,
11-
TopBottomPanel, Visuals,
11+
TopBottomPanel, Visuals, RichText, ComboBox,
1212
},
1313
epaint::FontId,
1414
Frame,
1515
};
1616
use egui_extras::{Column, TableBuilder};
17-
use proxyapi::*;
17+
use proxyapi::{*, hyper::Method};
1818
use serde::{Deserialize, Serialize};
1919

2020
#[derive(Serialize, Deserialize)]
@@ -40,15 +40,49 @@ impl Default for MitmProxyConfig {
4040
}
4141
}
4242

43+
44+
#[derive(Debug,Default,PartialEq, Eq)]
45+
pub enum MethodFilter {
46+
#[default]
47+
All,
48+
Only(Method),
49+
}
50+
impl MethodFilter{
51+
const METHODS: [(&'static str,Self);10]=[
52+
("All",MethodFilter::All),
53+
("GET",MethodFilter::Only(Method::GET)),
54+
("POST",MethodFilter::Only(Method::POST)),
55+
("PUT",MethodFilter::Only(Method::PUT)),
56+
("DELETE",MethodFilter::Only(Method::DELETE)),
57+
("PATCH",MethodFilter::Only(Method::PATCH)),
58+
("HEAD",MethodFilter::Only(Method::HEAD)),
59+
("OPTIONS",MethodFilter::Only(Method::OPTIONS)),
60+
("CONNECT",MethodFilter::Only(Method::CONNECT)),
61+
("TRACE",MethodFilter::Only(Method::TRACE)),
62+
];
63+
}
64+
impl Display for MethodFilter {
65+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66+
if let Self::Only(method) = self {
67+
Display::fmt(method, f)
68+
}else {
69+
f.write_str("All")
70+
}
71+
}
72+
}
73+
74+
4375
struct MitmProxyState {
4476
selected_request: Option<usize>,
77+
selected_request_method: MethodFilter,
4578
detail_option: InfoOptions,
4679
}
4780

4881
impl MitmProxyState {
4982
fn new() -> Self {
5083
Self {
5184
selected_request: None,
85+
selected_request_method: MethodFilter::All,
5286
detail_option: InfoOptions::Request,
5387
}
5488
}
@@ -155,18 +189,31 @@ impl MitmProxy {
155189

156190
header.col(|_ui| ());
157191
})
158-
.body(|body| {
159-
body.rows(text_height, self.requests.len(), |row_index, mut row| {
160-
self.requests
161-
.get_mut(row_index)
162-
.expect("Problem with index")
163-
.render_row(&mut row);
164-
row.col(|ui| {
165-
if ui.button("🔎").clicked() {
166-
self.state.selected_request = Some(row_index);
167-
}
168-
});
169-
})
192+
.body(|mut body| {
193+
if let MethodFilter::Only(filter_method) = &self.state.selected_request_method {
194+
for (row_index, request) in self.requests.iter().enumerate().filter(|r|r.1.should_show(&filter_method)) {
195+
body.row(text_height, |mut row|{
196+
request.render_row(&mut row);
197+
row.col(|ui| {
198+
if ui.button("🔎").clicked() {
199+
self.state.selected_request = Some(row_index);
200+
}
201+
});
202+
});
203+
}
204+
}else{
205+
body.rows(text_height, self.requests.len(), |row_index, mut row| {
206+
self.requests
207+
.get_mut(row_index)
208+
.expect("Problem with index")
209+
.render_row(&mut row);
210+
row.col(|ui| {
211+
if ui.button("🔎").clicked() {
212+
self.state.selected_request = Some(row_index);
213+
}
214+
});
215+
})
216+
}
170217
});
171218
}
172219

@@ -247,6 +294,23 @@ impl MitmProxy {
247294
})
248295
.on_hover_text("Toggle theme");
249296

297+
298+
299+
const COMBOBOX_TEXT_SIZE:f32=15.;
300+
ComboBox::from_label("")
301+
.selected_text(RichText::new(format!("{} Requests",&self.state.selected_request_method)).size(COMBOBOX_TEXT_SIZE))
302+
.wrap(false)
303+
.show_ui(ui, |ui| {
304+
ui.style_mut().wrap = Some(false);
305+
for (method_str, method) in MethodFilter::METHODS {
306+
ui.selectable_value(
307+
&mut self.state.selected_request_method,
308+
method,
309+
RichText::new(method_str).size(COMBOBOX_TEXT_SIZE)
310+
);
311+
}
312+
});
313+
250314
if close_btn.clicked() {
251315
frame.close();
252316
}

mitm_proxy/src/requests.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use std::collections::HashMap;
22

33
use eframe::egui::{self};
44
use egui_extras::TableRow;
5-
use proxyapi::*;
5+
use proxyapi::{*, hyper::Method};
66

77
struct Request {
8+
http_method: Method,
89
method: String,
910
uri: String,
1011
version: String,
@@ -15,6 +16,7 @@ struct Request {
1516

1617
impl Request {
1718
fn new(
19+
http_method: Method,
1820
method: String,
1921
uri: String,
2022
version: String,
@@ -23,6 +25,7 @@ impl Request {
2325
time: i64,
2426
) -> Self {
2527
Self {
28+
http_method,
2629
method,
2730
uri,
2831
version,
@@ -93,6 +96,7 @@ impl From<Output> for RequestInfo {
9396
fn from(value: Output) -> Self {
9497
let request = match value.req() {
9598
Some(r) => Some(Request::new(
99+
r.http_method().clone(),
96100
r.method().to_string(),
97101
r.uri().to_string(),
98102
r.version().to_string(),
@@ -180,14 +184,22 @@ impl RequestInfo {
180184
}
181185
}
182186

187+
pub fn should_show(&self, method:&Method)->bool {
188+
if let Some(req) = &self.request {
189+
req.http_method == method
190+
}else{
191+
false
192+
}
193+
}
194+
183195
pub fn show_details(&mut self, ui: &mut egui::Ui) {
184196
ui.label(match &self.details {
185197
Some(_) => "Some details",
186198
None => "No details",
187199
});
188200
}
189201

190-
pub fn render_row(&mut self, row: &mut TableRow) {
202+
pub fn render_row(&self, row: &mut TableRow) {
191203
let req = self.request.as_ref().unwrap();
192204
let res = self.response.as_ref().unwrap();
193205
let time = (res.time as f64 - req.time as f64) * 10_f64.powf(-9.0) as f64;

proxyapi/src/output.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::{collections::HashMap, sync::mpsc::SyncSender};
22

33

44
use async_trait::async_trait;
5-
use http::{HeaderMap, Version, Response, Request};
5+
use http::{HeaderMap, Version, Response, Request, Method};
66
use hyper::{Body};
77

88
use crate::{HttpHandler, HttpContext, RequestResponse};
@@ -55,6 +55,7 @@ impl HttpHandler for Output {
5555
async fn handle_request(&mut self, _ctx: &HttpContext, req: Request<Body>, ) -> RequestResponse {
5656
println!("request{:?}\n", req);
5757
let output_request = OutputRequest::new(
58+
req.method().clone(),
5859
req.method().to_string(),
5960
req.uri().to_string(),
6061
req.version().to_string(),
@@ -91,6 +92,7 @@ impl HttpHandler for Output {
9192

9293
#[derive(Clone, Debug)]
9394
pub struct OutputRequest {
95+
http_method: Method,
9496
method: String,
9597
uri: String,
9698
version: String,
@@ -101,6 +103,7 @@ pub struct OutputRequest {
101103

102104
impl OutputRequest {
103105
fn new(
106+
http_method: Method,
104107
method: String,
105108
uri: String,
106109
version: String,
@@ -109,6 +112,7 @@ impl OutputRequest {
109112
time: i64,
110113
) -> Self {
111114
Self {
115+
http_method,
112116
method,
113117
uri,
114118
version,
@@ -118,6 +122,10 @@ impl OutputRequest {
118122
}
119123
}
120124

125+
pub fn http_method(&self) -> &Method {
126+
&self.http_method
127+
}
128+
121129
pub fn method(&self) -> &String {
122130
&self.method
123131
}

0 commit comments

Comments
 (0)