2020import multiprocessing
2121import sys
2222import inspect
23- import pathlib
2423
2524from typing import Optional , Union , Dict , List , TypeVar , Type , cast , Any , Tuple
2625
3332from .constants import DEFAULT_PAC_FILE_URL_PATH , DEFAULT_PAC_FILE , DEFAULT_PLUGINS , DEFAULT_PID_FILE , DEFAULT_PORT
3433from .constants import DEFAULT_NUM_WORKERS , DEFAULT_VERSION , DEFAULT_OPEN_FILE_LIMIT , DEFAULT_IPV6_HOSTNAME
3534from .constants import DEFAULT_SERVER_RECVBUF_SIZE , DEFAULT_CLIENT_RECVBUF_SIZE , DEFAULT_STATIC_SERVER_DIR
36- from .constants import DEFAULT_ENABLE_DASHBOARD , COMMA , DOT
35+ from .constants import DEFAULT_ENABLE_DASHBOARD , DEFAULT_DATA_DIRECTORY_PATH , COMMA , DOT
36+ from .constants import PLUGIN_HTTP_PROXY , PLUGIN_WEB_SERVER , PLUGIN_PAC_FILE
37+ from .constants import PLUGIN_DEVTOOLS_PROTOCOL , PLUGIN_DASHBOARD , PLUGIN_INSPECT_TRAFFIC
3738from .version import __version__
3839
3940__homepage__ = 'https://github.com/abhinavsingh/proxy.py'
4950class Flags :
5051 """Contains all input flags and inferred input parameters."""
5152
52- ROOT_DATA_DIR_NAME = '.proxy.py'
53- GENERATED_CERTS_DIR_NAME = 'certificates'
54-
5553 def __init__ (
5654 self ,
5755 auth_code : Optional [bytes ] = DEFAULT_BASIC_AUTH ,
@@ -112,16 +110,25 @@ def __init__(
112110 self .devtools_ws_path : bytes = devtools_ws_path
113111 self .enable_events : bool = enable_events
114112
115- self .proxy_py_data_dir = os .path .join (
116- str (pathlib .Path .home ()), self .ROOT_DATA_DIR_NAME )
113+ self .proxy_py_data_dir = DEFAULT_DATA_DIRECTORY_PATH
117114 os .makedirs (self .proxy_py_data_dir , exist_ok = True )
118115
119116 self .ca_cert_dir : Optional [str ] = ca_cert_dir
120117 if self .ca_cert_dir is None :
121118 self .ca_cert_dir = os .path .join (
122- self .proxy_py_data_dir , self . GENERATED_CERTS_DIR_NAME )
119+ self .proxy_py_data_dir , 'certificates' )
123120 os .makedirs (self .ca_cert_dir , exist_ok = True )
124121
122+ def tls_interception_enabled (self ) -> bool :
123+ return self .ca_key_file is not None and \
124+ self .ca_cert_dir is not None and \
125+ self .ca_signing_key_file is not None and \
126+ self .ca_cert_file is not None
127+
128+ def encryption_enabled (self ) -> bool :
129+ return self .keyfile is not None and \
130+ self .certfile is not None
131+
125132 @classmethod
126133 def initialize (
127134 cls : Type [T ],
@@ -138,51 +145,59 @@ def initialize(
138145 'A future version of pip will drop support for Python 2.7.' )
139146 sys .exit (1 )
140147
141- args = Flags .init_parser ().parse_args (input_args )
148+ parser = Flags .init_parser ()
149+ args = parser .parse_args (input_args )
142150
151+ # Print version and exit
143152 if args .version :
144153 print (__version__ )
145154 sys .exit (0 )
146155
147- if (args .cert_file and args .key_file ) and \
148- (args .ca_key_file and args .ca_cert_file and args .ca_signing_key_file ):
149- print ('You can either enable end-to-end encryption OR TLS interception,'
150- 'not both together.' )
151- sys .exit (1 )
152-
153- auth_code = None
154- if args .basic_auth :
155- auth_code = b'Basic %s' % base64 .b64encode (bytes_ (args .basic_auth ))
156-
156+ # Setup logging module
157157 Flags .setup_logger (args .log_file , args .log_level , args .log_format )
158- Flags .set_open_file_limit (args .open_file_limit )
159158
160- http_proxy_plugin = 'proxy.http.proxy.HttpProxyPlugin'
161- web_server_plugin = 'proxy.http.server.HttpWebServerPlugin'
162- pac_file_plugin = 'proxy.http.server.HttpWebServerPacFilePlugin'
163- devtools_protocol_plugin = 'proxy.http.inspector.DevtoolsProtocolPlugin'
164- dashboard_plugin = 'proxy.dashboard.dashboard.ProxyDashboard'
165- inspect_traffic_plugin = 'proxy.dashboard.inspect_traffic.InspectTrafficPlugin'
159+ # Setup limits
160+ Flags .set_open_file_limit (args .open_file_limit )
166161
167162 default_plugins : List [Tuple [str , bool ]] = []
168163 if args .enable_dashboard :
169- default_plugins .append ((web_server_plugin , True ))
164+ default_plugins .append ((PLUGIN_WEB_SERVER , True ))
170165 args .enable_static_server = True
171- default_plugins .append ((dashboard_plugin , True ))
172- default_plugins .append ((inspect_traffic_plugin , True ))
166+ default_plugins .append ((PLUGIN_DASHBOARD , True ))
167+ default_plugins .append ((PLUGIN_INSPECT_TRAFFIC , True ))
173168 args .enable_events = True
174169 args .enable_devtools = True
175170 if args .enable_devtools :
176- default_plugins .append ((devtools_protocol_plugin , True ))
177- default_plugins .append ((web_server_plugin , True ))
171+ default_plugins .append ((PLUGIN_DEVTOOLS_PROTOCOL , True ))
172+ default_plugins .append ((PLUGIN_WEB_SERVER , True ))
178173 if not args .disable_http_proxy :
179- default_plugins .append ((http_proxy_plugin , True ))
174+ default_plugins .append ((PLUGIN_HTTP_PROXY , True ))
180175 if args .enable_web_server or \
181176 args .pac_file is not None or \
182177 args .enable_static_server :
183- default_plugins .append ((web_server_plugin , True ))
178+ default_plugins .append ((PLUGIN_WEB_SERVER , True ))
184179 if args .pac_file is not None :
185- default_plugins .append ((pac_file_plugin , True ))
180+ default_plugins .append ((PLUGIN_PAC_FILE , True ))
181+
182+ plugins = Flags .load_plugins (
183+ bytes_ (
184+ '%s,%s' %
185+ (text_ (COMMA ).join (collections .OrderedDict (default_plugins ).keys ()),
186+ opts .get ('plugins' , args .plugins ))))
187+
188+ # proxy.py currently cannot serve over HTTPS and perform TLS interception
189+ # at the same time. Check if user is trying to enable both feature
190+ # at the same time.
191+ if (args .cert_file and args .key_file ) and \
192+ (args .ca_key_file and args .ca_cert_file and args .ca_signing_key_file ):
193+ print ('You can either enable end-to-end encryption OR TLS interception,'
194+ 'not both together.' )
195+ sys .exit (1 )
196+
197+ # Generate auth_code required for basic authentication if enabled
198+ auth_code = None
199+ if args .basic_auth :
200+ auth_code = b'Basic %s' % base64 .b64encode (bytes_ (args .basic_auth ))
186201
187202 return cls (
188203 auth_code = cast (Optional [bytes ], opts .get ('auth_code' , auth_code )),
@@ -258,23 +273,9 @@ def initialize(
258273 opts .get (
259274 'enable_events' ,
260275 args .enable_events )),
261- plugins = Flags .load_plugins (
262- bytes_ (
263- '%s,%s' %
264- (text_ (COMMA ).join (collections .OrderedDict (default_plugins ).keys ()),
265- opts .get ('plugins' , args .plugins )))),
276+ plugins = plugins ,
266277 pid_file = cast (Optional [str ], opts .get ('pid_file' , args .pid_file )))
267278
268- def tls_interception_enabled (self ) -> bool :
269- return self .ca_key_file is not None and \
270- self .ca_cert_dir is not None and \
271- self .ca_signing_key_file is not None and \
272- self .ca_cert_file is not None
273-
274- def encryption_enabled (self ) -> bool :
275- return self .keyfile is not None and \
276- self .certfile is not None
277-
278279 @staticmethod
279280 def init_parser () -> argparse .ArgumentParser :
280281 """Initializes and returns argument parser."""
0 commit comments