Merge pull request #35 from pbi-qfs/develop
Added --pac-file option to serve a Proxy Autoconfig file
This commit is contained in:
commit
a0021cdb3a
|
@ -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
|
||||
|
|
40
proxy.py
40
proxy.py
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue