diff --git a/cert.py b/cert.py
index 6d2688d..78aa00a 100755
--- a/cert.py
+++ b/cert.py
@@ -56,9 +56,9 @@ def get_cert(name, config):
cafile: the CA file to create dummpy cert files
certdir: the path where cert files are looked for or created
'''
- certfile = os.path.join(config.CERTDIR, name + '.crt')
+ certfile = os.path.join(config.certdir, name + '.crt')
if not os.path.exists(certfile):
- dummy_cert(config.CA, certfile, name)
+ dummy_cert(config.ca, certfile, name)
return certfile
diff --git a/data/error.html b/data/error.html
new file mode 100644
index 0000000..de02eae
--- /dev/null
+++ b/data/error.html
@@ -0,0 +1,107 @@
+
+
+
+
+
+ $server: Error $code
+
+
+
+
+ $code
+
+
+
+ This is $server
+ on $hostname ($address), port $port
+
+
+
+
+
+ $message:
+
+ Your request for $url could not be fulfilled
+ because an error occured.
+
+
+
+
+ More information:
+ $explain
+ Error generated on $now.
+
+
+
+
+
diff --git a/main.py b/main.py
index c73f02d..81786f4 100755
--- a/main.py
+++ b/main.py
@@ -29,16 +29,19 @@ _name = 'privoxy-tls'
class LoadConfig:
def __init__(self, configfile):
- self.config = configparser.ConfigParser(allow_no_value=True,
- inline_comment_prefixes=('#',))
+ self.config = configparser.ConfigParser(
+ allow_no_value=True, delimiters=('=',),
+ inline_comment_prefixes=('#',))
self.config.read(configfile)
- self.PROXADDR = self.config['General'].get('ProxAddr')
- self.FRONTPORT = int(self.config['General'].get('FrontPort'))
- self.REARPORT = int(self.config['General'].get('RearPort'))
- self.GeneralPROXY = self.config['General'].get('DefaultProxy')
- self.LOGLEVEL = self.config['General'].get('LogLevel')
- self.CA = self.config['General'].get('CACert')
- self.CERTDIR = self.config['General'].get('CertDir')
+ self.proxy_name = self.config['General'].get('ProxAddr')
+ self.front_name = self.config['General'].get('FrontAddr', 'localhost')
+ self.rear_name = self.config['General'].get('RearAddr', 'localhost')
+ self.front_port = int(self.config['General'].get('FrontPort'))
+ self.rear_port = int(self.config['General'].get('RearPort'))
+ self.proxy = self.config['General'].get('DefaultProxy')
+ self.loglevel = self.config['General'].get('LogLevel')
+ self.ca = self.config['General'].get('CACert')
+ self.certdir = self.config['General'].get('CertDir')
class ConnectionPools:
@@ -307,7 +310,7 @@ class FrontRequestHandler(ProxyRequestHandler):
logger.warning(f'{self.reqNum:03d} [F] {e} on '
f'"{self.command} {url}"')
except (urllib3.exceptions.HTTPError,) as e:
- self.sendout_error(url, 502, message="HTTPError", explain=e)
+ self.sendout_error(url, 502, message="HTTP Error", explain=e)
logger.warning(f'{self.reqNum:03d} [F] {e} on '
f'"{self.command} {url}"')
finally:
@@ -323,7 +326,7 @@ class RearRequestHandler(ProxyRequestHandler):
Supposed to be the parent proxy for Privoxy for tagged requests
Convert http request to https
"""
- server_version = f'{_name} front/{__version__}'
+ server_version = f'{_name} rear/{__version__}'
def do_METHOD(self):
"Convert http request to https"
@@ -409,7 +412,7 @@ class RearRequestHandler(ProxyRequestHandler):
logger.warning(f'{self.reqNum:03d} [R]{prefix} '
f'"{self.command} {url}" {e}')
except (urllib3.exceptions.HTTPError,) as e:
- self.sendout_error(url, 502, message="HTTPError", explain=e)
+ self.sendout_error(url, 502, message="HTTP Error", explain=e)
logger.warning(f'{self.reqNum:03d} [R]{prefix} '
f'"{self.command} {url}" {e}')
@@ -423,16 +426,18 @@ class RearRequestHandler(ProxyRequestHandler):
def main():
urllib3.disable_warnings()
- logger.setLevel(getattr(logging, config.LOGLEVEL, logging.INFO))
+ logger.setLevel(getattr(logging, config.loglevel, logging.INFO))
handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s %(message)s', datefmt='[%H:%M]')
handler.setFormatter(formatter)
logger.addHandler(handler)
- frontserver = FrontServer(('', config.FRONTPORT), FrontRequestHandler)
- rearserver = RearServer(('', config.REARPORT), RearRequestHandler)
- frontserver.config = config
- for worker in (frontserver.serve_forever, rearserver.serve_forever,
+ frontserver = FrontServer((config.front_name, config.front_port),
+ FrontRequestHandler)
+ rearserver = RearServer((config.rear_name, config.rear_port),
+ RearRequestHandler)
+ for worker in (frontserver.serve_forever,
+ rearserver.serve_forever,
pools.reloadConfig):
thread = threading.Thread(target=worker)
thread.daemon = True
@@ -440,10 +445,10 @@ def main():
print('=' * 40)
print(f'{_name} {__version__} (urllib3/{urllib3.__version__})')
- print(f'Front : localhost:{config.FRONTPORT}')
- print(f'Privoxy : {config.PROXADDR}')
- print(f'Rear : localhost:{config.REARPORT}')
- print(f'Parent : {config.GeneralPROXY}')
+ print(f'Front : {config.front_name}:{config.front_port}')
+ print(f'Privoxy : {config.proxy_name}')
+ print(f'Rear : {config.rear_name}:{config.rear_port}')
+ print(f'Proxy : {config.proxy}')
print('=' * 40)
while True:
time.sleep(1)
@@ -461,7 +466,7 @@ if __name__ == '__main__':
logger = logging.getLogger(__name__)
config = LoadConfig(CONFIG)
proxpool = urllib3.ProxyManager(
- config.PROXADDR, num_pools=10, maxsize=8,
+ config.proxy_name, num_pools=10, maxsize=8,
timeout=urllib3.util.timeout.Timeout(
connect=90.0, read=310.0))
pools = ConnectionPools(CONFIG)
diff --git a/proxy.py b/proxy.py
index e912420..623b994 100755
--- a/proxy.py
+++ b/proxy.py
@@ -12,6 +12,8 @@ import cgi
import socket
import select
import ssl
+import string
+import pathlib
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn
@@ -20,23 +22,36 @@ from cert import get_cert
_name = 'proxy'
logger = logging.getLogger('__main__')
-message_format = '''\
-
-
-
-
- Proxy Error: {code}
-
-
- {code}: {message}
- The following error occurred while
- trying to access {url}
-
- {explain}
-
Generated on {now} by {server}.
-
-
-'''
+data = pathlib.Path(__file__).parent / 'data'
+error_template = string.Template(open(data / 'error.html').read())
+
+
+def walk_traceback(e, n=0):
+ '''
+ Produce an HTML formatted stack trace
+ given an exception.
+ '''
+ partial = []
+ ul = lambda xs: ('- '
+ + '
\n- '.join(xs)
+ + '
')
+
+ for i, arg in enumerate(e.args):
+ name = ((''
+ + type(e).__name__
+ + '') if i == 0 else '')
+ if isinstance(arg, str):
+ partial.append(
+ name + ' - '
+ + arg.replace('<', '<').replace('>', '>'))
+ else:
+ partial.append(name)
+
+ if isinstance(arg, Exception):
+ partial.append(walk_traceback(arg, n+1))
+ if n == 0:
+ partial.append(walk_traceback(e.reason, n+1))
+ return ul(partial)
def read_write(socket1, socket2, max_idling=10):
@@ -157,10 +172,15 @@ class ProxyRequestHandler(BaseHTTPRequestHandler):
message = shortmsg
if explain is None:
explain = longmsg
- content = message_format.format(
+
+ content = error_template.substitute(
code=code, message=message,
- explain=explain, url=url,
- now=datetime.today(),
+ explain=walk_traceback(explain),
+ url=url,
+ hostname=self.server.server_name,
+ address=self.server.server_address[0],
+ port=self.server.server_port,
+ now=datetime.today().isoformat(sep=' ', timespec='seconds'),
server=self.server_version)
body = content.encode('UTF-8', 'replace')
self.send_response_only(code, message)