83 lines
2.8 KiB
Python
83 lines
2.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
proxy.py
|
|
~~~~~~~~
|
|
⚡⚡⚡ Fast, Lightweight, Pluggable, TLS interception capable proxy server focused on
|
|
Network monitoring, controls & Application development, testing, debugging.
|
|
|
|
:copyright: (c) 2013-present by Abhinav Singh and contributors.
|
|
:license: BSD, see LICENSE for more details.
|
|
"""
|
|
import gzip
|
|
from typing import List, Tuple, Optional, Any
|
|
|
|
from .plugin import HttpWebServerBasePlugin
|
|
from .protocols import httpProtocolTypes
|
|
from ..websocket import WebsocketFrame
|
|
from ..parser import HttpParser
|
|
from ...common.utils import bytes_, text_, build_http_response
|
|
from ...common.flag import flags
|
|
from ...common.constants import DEFAULT_PAC_FILE, DEFAULT_PAC_FILE_URL_PATH
|
|
|
|
|
|
flags.add_argument(
|
|
'--pac-file',
|
|
type=str,
|
|
default=DEFAULT_PAC_FILE,
|
|
help='A file (Proxy Auto Configuration) or string to serve when '
|
|
'the server receives a direct file request. '
|
|
'Using this option enables proxy.HttpWebServerPlugin.',
|
|
)
|
|
flags.add_argument(
|
|
'--pac-file-url-path',
|
|
type=str,
|
|
default=text_(DEFAULT_PAC_FILE_URL_PATH),
|
|
help='Default: %s. Web server path to serve the PAC file.' %
|
|
text_(DEFAULT_PAC_FILE_URL_PATH),
|
|
)
|
|
|
|
|
|
class HttpWebServerPacFilePlugin(HttpWebServerBasePlugin):
|
|
|
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
super().__init__(*args, **kwargs)
|
|
self.pac_file_response: Optional[memoryview] = None
|
|
self.cache_pac_file_response()
|
|
|
|
def routes(self) -> List[Tuple[int, str]]:
|
|
if self.flags.pac_file_url_path:
|
|
return [
|
|
(httpProtocolTypes.HTTP, text_(self.flags.pac_file_url_path)),
|
|
(httpProtocolTypes.HTTPS, text_(self.flags.pac_file_url_path)),
|
|
]
|
|
return [] # pragma: no cover
|
|
|
|
def handle_request(self, request: HttpParser) -> None:
|
|
if self.flags.pac_file and self.pac_file_response:
|
|
self.client.queue(self.pac_file_response)
|
|
|
|
def on_websocket_open(self) -> None:
|
|
pass # pragma: no cover
|
|
|
|
def on_websocket_message(self, frame: WebsocketFrame) -> None:
|
|
pass # pragma: no cover
|
|
|
|
def on_websocket_close(self) -> None:
|
|
pass # pragma: no cover
|
|
|
|
def cache_pac_file_response(self) -> None:
|
|
if self.flags.pac_file:
|
|
try:
|
|
with open(self.flags.pac_file, 'rb') as f:
|
|
content = f.read()
|
|
except IOError:
|
|
content = bytes_(self.flags.pac_file)
|
|
self.pac_file_response = memoryview(
|
|
build_http_response(
|
|
200, reason=b'OK', headers={
|
|
b'Content-Type': b'application/x-ns-proxy-autoconfig',
|
|
b'Content-Encoding': b'gzip',
|
|
}, body=gzip.compress(content),
|
|
),
|
|
)
|