1
- use std:: {
2
- fmt:: { Display } ,
3
- sync:: mpsc:: Receiver ,
4
- } ;
1
+ use std:: { fmt:: Display , net:: SocketAddr } ;
5
2
6
3
use crate :: {
4
+ managed_proxy:: ManagedProxy ,
7
5
requests:: { InfoOptions , RequestInfo } ,
8
6
PADDING ,
9
7
} ;
10
8
11
9
use eframe:: {
12
10
egui:: {
13
11
self , ComboBox , FontData , FontDefinitions , FontFamily , Grid , Layout , RichText , ScrollArea ,
14
- Style , TextStyle :: * , TopBottomPanel , Visuals ,
12
+ Style , TextEdit , TextStyle :: * , TopBottomPanel , Visuals ,
15
13
} ,
16
- epaint:: FontId ,
14
+ epaint:: { Color32 , FontId } ,
17
15
Frame ,
18
16
} ;
19
17
use egui_extras:: { Column , TableBuilder } ;
20
- use proxyapi:: { hyper:: Method , * } ;
18
+ use proxyapi:: hyper:: Method ;
21
19
use serde:: { Deserialize , Serialize } ;
22
20
23
21
#[ derive( Serialize , Deserialize ) ]
@@ -77,6 +75,7 @@ struct MitmProxyState {
77
75
selected_request : Option < usize > ,
78
76
selected_request_method : MethodFilter ,
79
77
detail_option : InfoOptions ,
78
+ listen_on : String ,
80
79
}
81
80
82
81
impl MitmProxyState {
@@ -85,6 +84,7 @@ impl MitmProxyState {
85
84
selected_request : None ,
86
85
selected_request_method : MethodFilter :: All ,
87
86
detail_option : InfoOptions :: Request ,
87
+ listen_on : "127.0.0.1:8100" . to_string ( ) ,
88
88
}
89
89
}
90
90
}
@@ -93,11 +93,11 @@ pub struct MitmProxy {
93
93
requests : Vec < RequestInfo > ,
94
94
config : MitmProxyConfig ,
95
95
state : MitmProxyState ,
96
- rx : Receiver < ProxyHandler > ,
96
+ proxy : Option < ManagedProxy > ,
97
97
}
98
98
99
99
impl MitmProxy {
100
- pub fn new ( cc : & eframe:: CreationContext < ' _ > , rx : Receiver < ProxyHandler > ) -> Self {
100
+ pub fn new ( cc : & eframe:: CreationContext < ' _ > ) -> Self {
101
101
Self :: configure_fonts ( cc) ;
102
102
let config: MitmProxyConfig = confy:: load ( "MitmProxy" , None ) . unwrap_or_default ( ) ;
103
103
let state = MitmProxyState :: new ( ) ;
@@ -106,7 +106,7 @@ impl MitmProxy {
106
106
requests : vec ! [ ] ,
107
107
config,
108
108
state,
109
- rx ,
109
+ proxy : None ,
110
110
}
111
111
}
112
112
@@ -117,6 +117,23 @@ impl MitmProxy {
117
117
}
118
118
}
119
119
120
+ fn start_proxy ( & mut self , addr : SocketAddr ) {
121
+ assert ! ( self . proxy. is_none( ) ) ;
122
+
123
+ self . proxy = Some ( ManagedProxy :: new ( addr) ) ;
124
+ self . requests = vec ! [ ] ;
125
+ }
126
+
127
+ fn stop_proxy ( & mut self ) {
128
+ assert ! ( self . proxy. is_some( ) ) ;
129
+
130
+ self . proxy . take ( ) ;
131
+ }
132
+
133
+ fn is_running ( & self ) -> bool {
134
+ return self . proxy . is_some ( ) ;
135
+ }
136
+
120
137
fn configure_fonts ( cc : & eframe:: CreationContext < ' _ > ) {
121
138
let mut fonts = FontDefinitions :: default ( ) ;
122
139
@@ -255,19 +272,14 @@ impl MitmProxy {
255
272
} ) ;
256
273
}
257
274
258
- pub fn update_requests ( & mut self ) -> Option < RequestInfo > {
259
- match self . rx . try_recv ( ) {
260
- Ok ( l) => {
261
- let ( request, response) = l. to_parts ( ) ;
262
- Some ( RequestInfo :: new ( request, response) )
263
- } ,
264
- _ => None ,
265
- }
266
- }
267
-
268
275
pub fn render_columns ( & mut self , ui : & mut egui:: Ui ) {
269
- if let Some ( request) = self . update_requests ( ) {
270
- self . requests . push ( request) ;
276
+ if !self . is_running ( ) {
277
+ return ;
278
+ }
279
+ if let Some ( ref mut proxy) = self . proxy {
280
+ if let Some ( request) = proxy. try_recv_request ( ) {
281
+ self . requests . push ( request) ;
282
+ }
271
283
}
272
284
273
285
if let Some ( i) = self . state . selected_request {
@@ -292,6 +304,37 @@ impl MitmProxy {
292
304
pub fn render_top_panel ( & mut self , ctx : & egui:: Context , _frame : & mut Frame ) {
293
305
TopBottomPanel :: top ( "top_panel" ) . show ( ctx, |ui| {
294
306
ui. add_space ( PADDING ) ;
307
+ egui:: menu:: bar ( ui, |ui| -> egui:: InnerResponse < _ > {
308
+ ui. with_layout ( Layout :: left_to_right ( eframe:: emath:: Align :: Min ) , |ui| {
309
+ if !self . is_running ( ) {
310
+ TextEdit :: singleline ( & mut self . state . listen_on ) . show ( ui) ;
311
+
312
+ match self . state . listen_on . parse :: < SocketAddr > ( ) {
313
+ Ok ( addr) => {
314
+ let start_button = ui. button ( "▶" ) . on_hover_text ( "Start" ) ;
315
+ if start_button. clicked ( ) {
316
+ self . start_proxy ( addr) ;
317
+ }
318
+ }
319
+ Err ( _err) => {
320
+ ui. label (
321
+ RichText :: new ( "Provided invalid IP address" )
322
+ . color ( Color32 :: RED ) ,
323
+ ) ;
324
+ }
325
+ } ;
326
+ } else {
327
+ TextEdit :: singleline ( & mut self . state . listen_on )
328
+ . interactive ( false )
329
+ . show ( ui) ;
330
+ let stop_button = ui. button ( "■" ) . on_hover_text ( "Stop" ) ;
331
+ if stop_button. clicked ( ) {
332
+ self . stop_proxy ( ) ;
333
+ }
334
+ }
335
+ } )
336
+ } ) ;
337
+
295
338
egui:: menu:: bar ( ui, |ui| -> egui:: InnerResponse < _ > {
296
339
ui. with_layout ( Layout :: left_to_right ( eframe:: emath:: Align :: Min ) , |ui| {
297
340
let clean_btn = ui. button ( "🚫" ) . on_hover_text ( "Clear" ) ;
@@ -326,14 +369,12 @@ impl MitmProxy {
326
369
} ) ;
327
370
328
371
ui. with_layout ( Layout :: right_to_left ( eframe:: emath:: Align :: Min ) , |ui| {
329
-
330
372
let theme_btn = ui
331
373
. button ( match self . config . dark_mode {
332
374
true => "🔆" ,
333
375
false => "🌙" ,
334
376
} )
335
377
. on_hover_text ( "Toggle theme" ) ;
336
-
337
378
338
379
if theme_btn. clicked ( ) {
339
380
self . config . dark_mode = !self . config . dark_mode
0 commit comments