mirror of
https://github.com/webrecorder/pywb.git
synced 2025-03-24 06:59:52 +01:00
https proxy support, CONNECT verb handling (uwsgi only)
This commit is contained in:
parent
bdf69ff1a9
commit
739f23da9e
@ -1,4 +1,4 @@
|
|||||||
PyWb 0.5.1
|
PyWb 0.5.2
|
||||||
==========
|
==========
|
||||||
|
|
||||||
.. image:: https://travis-ci.org/ikreymer/pywb.png?branch=develop
|
.. image:: https://travis-ci.org/ikreymer/pywb.png?branch=develop
|
||||||
|
@ -62,12 +62,16 @@ class ProxyRouter(object):
|
|||||||
self.unaltered = proxy_options.get('unaltered_replay', False)
|
self.unaltered = proxy_options.get('unaltered_replay', False)
|
||||||
|
|
||||||
def __call__(self, env):
|
def __call__(self, env):
|
||||||
|
if env['REQUEST_METHOD'] == 'CONNECT':
|
||||||
|
if not self.handle_connect(env):
|
||||||
|
return None
|
||||||
|
|
||||||
url = env['REL_REQUEST_URI']
|
url = env['REL_REQUEST_URI']
|
||||||
|
|
||||||
if url.endswith('/proxy.pac'):
|
if url.endswith('/proxy.pac'):
|
||||||
return self.make_pac_response(env)
|
return self.make_pac_response(env)
|
||||||
|
|
||||||
if not url.startswith('http://'):
|
if not url.startswith(('http://', 'https://')):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
proxy_auth = env.get('HTTP_PROXY_AUTHORIZATION')
|
proxy_auth = env.get('HTTP_PROXY_AUTHORIZATION')
|
||||||
@ -122,6 +126,72 @@ class ProxyRouter(object):
|
|||||||
|
|
||||||
return route.handler(wbrequest)
|
return route.handler(wbrequest)
|
||||||
|
|
||||||
|
def handle_connect(self, env):
|
||||||
|
import uwsgi
|
||||||
|
import socket
|
||||||
|
import ssl
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
fd = uwsgi.connection_fd()
|
||||||
|
conn = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
sock = socket.socket(_sock=conn)
|
||||||
|
|
||||||
|
if (self.use_default_coll or
|
||||||
|
len(self.routes) == 1 or
|
||||||
|
env.get('HTTP_PROXY_AUTHORIZATION') is not None):
|
||||||
|
|
||||||
|
sock.send('HTTP/1.0 200 Connection Established\r\n')
|
||||||
|
sock.send('Server: pywb proxy\r\n')
|
||||||
|
sock.send('\r\n')
|
||||||
|
else:
|
||||||
|
env['pywb.proxy_statusline'] = '407 Proxy Auth Required'
|
||||||
|
sock.send('HTTP/1.0 407 Proxy Auth Required\r\n')
|
||||||
|
sock.send('Server: pywb proxy\r\n')
|
||||||
|
sock.send('\r\n')
|
||||||
|
return False
|
||||||
|
|
||||||
|
ssl_sock = ssl.wrap_socket(sock, server_side=True,
|
||||||
|
certfile='/tmp/testcert.pem',
|
||||||
|
ssl_version=ssl.PROTOCOL_SSLv23)
|
||||||
|
|
||||||
|
env['pywb.proxy_ssl_sock'] = ssl_sock
|
||||||
|
|
||||||
|
buff = ssl_sock.recv(4096)
|
||||||
|
|
||||||
|
buffreader = BytesIO(buff)
|
||||||
|
|
||||||
|
statusline = buffreader.readline()
|
||||||
|
statusparts = statusline.split(' ')
|
||||||
|
|
||||||
|
if len(statusparts) < 3:
|
||||||
|
return
|
||||||
|
|
||||||
|
env['REQUEST_METHOD'] = statusparts[0]
|
||||||
|
env['REL_REQUEST_URI'] = ('https://' +
|
||||||
|
env['REL_REQUEST_URI'].replace(':443', '') +
|
||||||
|
statusparts[1])
|
||||||
|
|
||||||
|
env['SERVER_PROTOCOL'] = statusparts[2].strip()
|
||||||
|
|
||||||
|
queryparts = env['REL_REQUEST_URI'].split('?', 1)
|
||||||
|
env['PATH_INFO'] = queryparts[0]
|
||||||
|
env['QUERY_STRING'] = queryparts[1] if len(queryparts) > 1 else ''
|
||||||
|
|
||||||
|
while True:
|
||||||
|
line = buffreader.readline()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
|
||||||
|
parts = line.split(':')
|
||||||
|
if len(parts) < 2:
|
||||||
|
continue
|
||||||
|
|
||||||
|
name = 'HTTP_' + parts[0].replace('-', '_').upper()
|
||||||
|
env[name] = parts[1]
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
# Proxy Auto-Config (PAC) script for the proxy
|
# Proxy Auto-Config (PAC) script for the proxy
|
||||||
def make_pac_response(self, env):
|
def make_pac_response(self, env):
|
||||||
import os
|
import os
|
||||||
|
@ -50,6 +50,39 @@ class WSGIApp(object):
|
|||||||
|
|
||||||
# Top-level wsgi application
|
# Top-level wsgi application
|
||||||
def __call__(self, env, start_response):
|
def __call__(self, env, start_response):
|
||||||
|
if env['REQUEST_METHOD'] == 'CONNECT':
|
||||||
|
return self.handle_connect(env, start_response)
|
||||||
|
else:
|
||||||
|
return self.handle_methods(env, start_response)
|
||||||
|
|
||||||
|
def handle_connect(self, env, start_response):
|
||||||
|
def ssl_start_response(statusline, headers):
|
||||||
|
ssl_sock = env.get('pywb.proxy_ssl_sock')
|
||||||
|
if not ssl_sock:
|
||||||
|
return
|
||||||
|
|
||||||
|
env['pywb.proxy_statusline'] = statusline
|
||||||
|
|
||||||
|
ssl_sock.write('HTTP/1.1 ' + statusline + '\r\n')
|
||||||
|
for name, value in headers:
|
||||||
|
ssl_sock.write(name + ': ' + value + '\r\n')
|
||||||
|
|
||||||
|
resp_iter = self.handle_methods(env, ssl_start_response)
|
||||||
|
|
||||||
|
ssl_sock = env.get('pywb.proxy_ssl_sock')
|
||||||
|
if ssl_sock:
|
||||||
|
ssl_sock.write('\r\n')
|
||||||
|
|
||||||
|
for obj in resp_iter:
|
||||||
|
ssl_sock.write(obj)
|
||||||
|
|
||||||
|
ssl_sock.close()
|
||||||
|
|
||||||
|
start_response(env['pywb.proxy_statusline'], [])
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def handle_methods(self, env, start_response):
|
||||||
if env.get('SCRIPT_NAME') or not env.get('REQUEST_URI'):
|
if env.get('SCRIPT_NAME') or not env.get('REQUEST_URI'):
|
||||||
env['REL_REQUEST_URI'] = rel_request_uri(env)
|
env['REL_REQUEST_URI'] = rel_request_uri(env)
|
||||||
else:
|
else:
|
||||||
|
2
setup.py
2
setup.py
@ -34,7 +34,7 @@ class PyTest(TestCommand):
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='pywb',
|
name='pywb',
|
||||||
version='0.5.1',
|
version='0.5.2',
|
||||||
url='https://github.com/ikreymer/pywb',
|
url='https://github.com/ikreymer/pywb',
|
||||||
author='Ilya Kreymer',
|
author='Ilya Kreymer',
|
||||||
author_email='ikreymer@gmail.com',
|
author_email='ikreymer@gmail.com',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user