Created
June 17, 2012 06:01
-
-
Save zhuzhuor/2943603 to your computer and use it in GitHub Desktop.
A (Lame) Python WSGI HTTP Proxy based on Tornado
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
''' | |
A blocking HTTP proxy based on non-blocking Tornado... | |
-- for the sake of WSGI compatibility -- | |
also without HTTPS support... | |
''' | |
from tornado import web, wsgi, httpclient, escape | |
import httplib | |
# from pprint import pprint | |
disallowed_response_headers = set([ | |
'connection', | |
'keep-alive', | |
'proxy-authenticate', | |
'proxy-authorization', | |
'te', | |
'trailers', | |
'transfer-encoding', | |
'upgrade', | |
# all above are hop-by-hop headers | |
'content-encoding', # will cause errors | |
]) | |
class MainHandler(web.RequestHandler): | |
SUPPORTED_METHODS = ['GET', 'POST'] | |
def handle_response(self, response): | |
self.set_status(response.code) | |
# pprint(response.headers) | |
# check the last comment of http://goo.gl/4w5yj | |
for h in response.headers.keys(): | |
if h.lower() not in disallowed_response_headers: | |
list_values = response.headers.get_list(h) | |
for v in list_values: | |
# print h, v | |
self.add_header(h, v) | |
if response.body: | |
self.write(response.body) | |
def get(self): | |
# tornado-proxy by senko works without this | |
# wsgiref's handling is a little different from tornado | |
if self.request.uri.startswith('http%3A'): | |
url = 'http:' + self.request.uri[7:] | |
else: | |
url = self.request.uri | |
# pprint(self.request.headers) | |
headers = {h: v for (h, v) in self.request.headers.items() \ | |
if not h.lower().startswith('proxy') | |
} | |
http_req = httpclient.HTTPRequest( | |
url=url, | |
method=self.request.method, | |
body=self.request.body, | |
headers=headers, | |
follow_redirects=False, | |
allow_nonstandard_methods=True | |
) | |
client = httpclient.HTTPClient() | |
try: | |
response = client.fetch(http_req) | |
self.handle_response(response) | |
except httpclient.HTTPError, err: | |
self.handle_response(err.response) | |
except Exception, err: | |
self.set_status(500) | |
self.write('Internal Server Error: ' + str(err)) | |
finally: | |
self.finish() | |
# def post as get | |
post = get | |
# for fixing a small bug in tornado; please check http://goo.gl/zR4Pq | |
class MyWSGIApplication(wsgi.WSGIApplication): | |
def __call__(self, environ, start_response): | |
handler = web.Application.__call__(self, wsgi.HTTPRequest(environ)) | |
assert handler._finished | |
status = str(handler._status_code) + " " + \ | |
httplib.responses[handler._status_code] | |
headers = handler._headers.items() + handler._list_headers | |
if hasattr(handler, "_new_cookie"): | |
for cookie in handler._new_cookie.values(): | |
headers.append(("Set-Cookie", cookie.OutputString(None))) | |
start_response(status, | |
[(escape.native_str(k), escape.native_str(v)) | |
for (k, v) in headers]) | |
return handler._write_buffer | |
app = MyWSGIApplication([ | |
(r'.*', MainHandler), | |
]) | |
if __name__ == "__main__": | |
import wsgiref.simple_server | |
server = wsgiref.simple_server.make_server('', 8888, app) | |
server.serve_forever() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment