From e23444b766aaff5a484deef636d887dcaa30d5e1 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Thu, 13 Dec 2018 22:31:56 +0530 Subject: [PATCH] Update README to reflect basic auth support. Also refactor proxy exception handling code. --- README.md | 22 +++++++++++++--------- proxy.py | 19 +++++++++++-------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 3553f8f1..131cb9c8 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,15 @@ proxy.py ======== -Lightweight HTTP Proxy Server in Python. +Lightweight HTTP, HTTPS and WebSockets Proxy Server in Python. Features -------- - Distributed as a single file module -- No dependency other than the Python standard library -- Support for http, https, websockets request proxy +- No external dependency other than standard Python library +- Support for `http`, `https` and `websockets` request proxy +- Basic authentication support Install ------- @@ -17,24 +18,27 @@ To install proxy.py, simply: $ pip install proxy.py -This will add `proxy.py` inside your python environment bin folder. - Usage ----- ``` $ proxy.py -h -usage: proxy.py [-h] [--hostname HOSTNAME] [--port PORT] - [--log-level LOG_LEVEL] +usage: proxy.py [-h] [--hostname HOSTNAME] [--port PORT] [--backlog BACKLOG] + [--basic-auth BASIC_AUTH] [--log-level LOG_LEVEL] -proxy.py v0.1 +proxy.py v0.3 optional arguments: -h, --help show this help message and exit --hostname HOSTNAME Default: 127.0.0.1 --port PORT Default: 8899 + --backlog BACKLOG Default: 100. Maximum number of pending connections to + proxy server + --basic-auth BASIC_AUTH + Default: No authentication. Specify colon separated + user:password to enable basic authentication. --log-level LOG_LEVEL - DEBUG, INFO, WARNING, ERROR, CRITICAL + DEBUG, INFO (default), WARNING, ERROR, CRITICAL Having difficulty using proxy.py? Report at: https://github.com/abhinavsingh/proxy.py/issues/new diff --git a/proxy.py b/proxy.py index 2e71ad38..054aadea 100755 --- a/proxy.py +++ b/proxy.py @@ -294,13 +294,14 @@ class Connection(object): self.what = what # server or client def send(self, data): + # TODO: Gracefully handle BrokenPipeError exceptions return self.conn.send(data) def recv(self, b=8192): try: data = self.conn.recv(b) if len(data) == 0: - logger.debug('recvd 0 bytes from %s' % self.what) + logger.debug('rcvd 0 bytes from %s' % self.what) return None logger.debug('rcvd %d bytes from %s' % (len(data), self.what)) return data @@ -505,14 +506,9 @@ class Proxy(threading.Thread): try: self._process_request(data) - except ProxyAuthenticationFailed as e: + except (ProxyAuthenticationFailed, ProxyConnectionFailed) as e: logger.exception(e) - self.client.queue(PROXY_AUTHENTICATION_REQUIRED_RESPONSE_PKT) - self.client.flush() - return True - except ProxyConnectionFailed as e: - logger.exception(e) - self.client.queue(BAD_GATEWAY_RESPONSE_PKT) + self.client.queue(Proxy._get_response_pkt_by_exception(e)) self.client.flush() return True @@ -547,6 +543,13 @@ class Proxy(threading.Thread): logger.debug('client buffer is empty and maximum inactivity has reached, breaking') break + @staticmethod + def _get_response_pkt_by_exception(e): + if e.__class__.__name__ == 'ProxyAuthenticationFailed': + return PROXY_AUTHENTICATION_REQUIRED_RESPONSE_PKT + if e.__class__.__name__ == 'ProxyConnectionFailed': + return BAD_GATEWAY_RESPONSE_PKT + def run(self): logger.debug('Proxying connection %r' % self.client.conn) try: