Merge pull request #35 from pbi-qfs/develop

Added --pac-file option to serve a Proxy Autoconfig file
This commit is contained in:
Abhinav Singh 2019-06-03 23:32:36 -07:00 committed by GitHub
commit a0021cdb3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 5 deletions

View File

@ -14,6 +14,7 @@ Features
- Optimize for large file uploads and downloads
- IPv4 and IPv6 support
- Basic authentication support
- Can serve a PAC (Proxy Autoconfiguration) file
Install
-------
@ -36,6 +37,7 @@ usage: proxy.py [-h] [--hostname HOSTNAME] [--port PORT] [--backlog BACKLOG]
[--server-recvbuf-size SERVER_RECVBUF_SIZE]
[--client-recvbuf-size CLIENT_RECVBUF_SIZE]
[--log-level LOG_LEVEL]
[--pac-file AutoConfig]
proxy.py v0.3
@ -60,6 +62,9 @@ optional arguments:
RAM.
--log-level LOG_LEVEL
DEBUG, INFO (default), WARNING, ERROR, CRITICAL
--pac-file A file (Proxy Auto Configuration) or string to serve when
the server receives a direct file request.
Example: proxy.py --pac-file "function FindProxyForURL(url, host) { return 'PROXY localhost:8899; DIRECT'; }"
Having difficulty using proxy.py? Report at:
https://github.com/abhinavsingh/proxy.py/issues/new

View File

@ -94,6 +94,12 @@ PROXY_AUTHENTICATION_REQUIRED_RESPONSE_PKT = CRLF.join([
CRLF
]) + b'Proxy Authentication Required'
PAC_FILE_RESPONSE_PREFIX = CRLF.join([
b'HTTP/1.1 200 OK',
b'Content-Type: application/x-ns-proxy-autoconfig',
b'Connection: close',
CRLF
])
class ChunkParser(object):
"""HTTP chunked encoding response parser."""
@ -424,7 +430,7 @@ class Proxy(threading.Thread):
Accepts `Client` connection object and act as a proxy between client and server.
"""
def __init__(self, client, auth_code=None, server_recvbuf_size=8192, client_recvbuf_size=8192):
def __init__(self, client, auth_code=None, server_recvbuf_size=8192, client_recvbuf_size=8192, pac_file = None):
super(Proxy, self).__init__()
self.start_time = self._now()
@ -439,6 +445,8 @@ class Proxy(threading.Thread):
self.request = HttpParser(HttpParser.types.REQUEST_PARSER)
self.response = HttpParser(HttpParser.types.RESPONSE_PARSER)
self.pac_file = pac_file
@staticmethod
def _now():
return datetime.datetime.utcnow()
@ -478,6 +486,10 @@ class Proxy(threading.Thread):
else:
raise Exception('Invalid request\n%s' % self.request.raw)
if host == None and self.pac_file:
self._serve_pac_file()
return True
self.server = Server(host, port)
try:
logger.debug('connecting to server %s:%s' % (host, port))
@ -550,7 +562,7 @@ class Proxy(threading.Thread):
return True
try:
self._process_request(data)
return self._process_request(data)
except (ProxyAuthenticationFailed, ProxyConnectionFailed) as e:
logger.exception(e)
self.client.queue(Proxy._get_response_pkt_by_exception(e))
@ -570,6 +582,19 @@ class Proxy(threading.Thread):
return False
def _serve_pac_file(self):
logger.debug('serving pac file')
self.client.queue(PAC_FILE_RESPONSE_PREFIX)
try:
with open(self.pac_file) as f:
for line in f:
self.client.queue(line)
except IOError:
logger.debug('serving pac file directly')
self.client.queue(self.pac_file)
self.client.flush()
def _process(self):
while True:
rlist, wlist, xlist = self._get_waitable_lists()
@ -654,17 +679,19 @@ class HTTP(TCP):
"""
def __init__(self, hostname='127.0.0.1', port=8899, backlog=100,
auth_code=None, server_recvbuf_size=8192, client_recvbuf_size=8192):
auth_code=None, server_recvbuf_size=8192, client_recvbuf_size=8192, pac_file=None):
super(HTTP, self).__init__(hostname, port, backlog)
self.auth_code = auth_code
self.client_recvbuf_size = client_recvbuf_size
self.server_recvbuf_size = server_recvbuf_size
self.pac_file = pac_file
def handle(self, client):
proxy = Proxy(client,
auth_code=self.auth_code,
server_recvbuf_size=self.server_recvbuf_size,
client_recvbuf_size=self.client_recvbuf_size)
client_recvbuf_size=self.client_recvbuf_size,
pac_file=self.pac_file)
proxy.daemon = True
proxy.start()
@ -705,6 +732,8 @@ def main():
'Maximum number of files (TCP connections) '
'that proxy.py can open concurrently.')
parser.add_argument('--log-level', default='INFO', help='DEBUG, INFO (default), WARNING, ERROR, CRITICAL')
parser.add_argument('--pac-file', default='', help='A file (Proxy Auto Configuration) or string to serve when '
'the server receives a direct file request.')
args = parser.parse_args()
logging.basicConfig(level=getattr(logging, args.log_level),
@ -722,7 +751,8 @@ def main():
backlog=int(args.backlog),
auth_code=auth_code,
server_recvbuf_size=int(args.server_recvbuf_size),
client_recvbuf_size=int(args.client_recvbuf_size))
client_recvbuf_size=int(args.client_recvbuf_size),
pac_file=args.pac_file)
proxy.run()
except KeyboardInterrupt:
pass