Mandaye now working for a basic reverse proxy
* mandaye/dispatchers/default.py; fix target
* mandaye/handlers/default.py: add urllib2 handlers
* mandaye/response.py: fix headers
* mandaye/server.py: fix the server
* pocs/poc1.py: revert to 6e75df935d
This commit is contained in:
parent
8ceb28cae8
commit
100ca8fea0
|
@ -10,4 +10,4 @@ class Dispatcher(object):
|
|||
if not query_string:
|
||||
return self.target + path
|
||||
else:
|
||||
return self.traget + path + "?" + query_string
|
||||
return self.target + path + "?" + query_string
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
'''
|
||||
Default urllib2 handlers for Mandaye
|
||||
'''
|
||||
|
||||
import urllib
|
||||
import urllib2
|
||||
|
||||
class MandayeRedirectHandler(urllib2.HTTPRedirectHandler):
|
||||
|
||||
def http_error_302(self, req, fp, code, msg, headers):
|
||||
""" Disable the auto """
|
||||
infourl = urllib.addinfourl(fp, headers, req.get_full_url())
|
||||
infourl.code = code
|
||||
infourl.msg = msg
|
||||
return infourl
|
||||
|
||||
class MandayeErrorHandler(urllib2.HTTPDefaultErrorHandler):
|
||||
def http_error_default(self, req, fp, code, msg, headers):
|
||||
result = urllib2.HTTPError(req.get_full_url(), code, msg, headers, fp)
|
||||
result.status = code
|
||||
return result
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ class MandayeResponse(object):
|
|||
"""
|
||||
code: integer return code (200, 302, 404, ..)
|
||||
status: string with http status (ex: OK, Not Found, ...)
|
||||
headers: an array with the headers
|
||||
headers: dictionary with the headers
|
||||
content: the string with a response content
|
||||
"""
|
||||
self.code = code
|
||||
|
@ -16,5 +16,5 @@ class MandayeResponse(object):
|
|||
self.content = content
|
||||
|
||||
|
||||
_404 = MandayeResponse(404, 'Not found', [], '')
|
||||
_502 = MandayeResponse(502, 'Bad Gateway', [], '')
|
||||
_404 = MandayeResponse(404, 'Not found', {}, '')
|
||||
_502 = MandayeResponse(502, 'Bad Gateway', {}, '')
|
||||
|
|
|
@ -7,13 +7,18 @@ import config
|
|||
import urllib
|
||||
import urllib2
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import poster.streaminghttp
|
||||
from cgi import escape
|
||||
from gevent.pywsgi import WSGIServer
|
||||
|
||||
from handlers.default import MandayeRedirectHandler, MandayeErrorHandler
|
||||
from response import _404, _502
|
||||
from response import MandayeResponse
|
||||
|
||||
|
||||
# Init poster
|
||||
opener = poster.streaminghttp.register_openers()
|
||||
|
||||
|
@ -38,7 +43,7 @@ class RequestApp(object):
|
|||
def _get_dispatcher(self, local_host, path_info):
|
||||
''' return a Dispatcher instance '''
|
||||
if config.hosts.has_key(local_host):
|
||||
for url in config[local_host]:
|
||||
for url in config.hosts[local_host]:
|
||||
if re.match(url[0], path_info):
|
||||
return url[1]
|
||||
return None
|
||||
|
@ -59,13 +64,13 @@ class RequestApp(object):
|
|||
for name in (name for name in self.env if name.startswith('HTTP_')):
|
||||
value = self.env[name]
|
||||
if name == "HTTP_REFERER":
|
||||
referer = value.replace(self.env["HTTP_HOST"], self.config['remote_host'])
|
||||
referer = value.replace(self.env["HTTP_HOST"], self.dispatcher.target)
|
||||
req.add_header("Referer", referer)
|
||||
if name != "HTTP_HOST" and name != "HTTP_REFERER":
|
||||
name = name.split('HTTP_')[1].replace('_', '-')
|
||||
req.add_header(name, value)
|
||||
try:
|
||||
opener = urllib2.build_opener(RpRedirectHandler, DefaultErrorHandler)
|
||||
opener = urllib2.build_opener(MandayeRedirectHandler, MandayeErrorHandler)
|
||||
response = opener.open(req)
|
||||
except Exception:
|
||||
ex = sys.exc_info()[1]
|
||||
|
@ -73,23 +78,23 @@ class RequestApp(object):
|
|||
sys.stderr.write('error while reading %s:\n' % path)
|
||||
traceback.print_exc()
|
||||
tb = traceback.format_exc()
|
||||
response = _502
|
||||
error_str = escape(str(ex) or ex.__class__.__name__ or 'Error')
|
||||
_502.content = '<h1>%s</h1><h2>%s</h2><pre>%s</pre>' % \
|
||||
(error_str, escape(path), escape(tb))
|
||||
_502.headers = [('Content-Type', 'text/html')]
|
||||
_502.headers = {'Content-Type': 'text/html'}
|
||||
return self.on_response(start_response, _502)
|
||||
else:
|
||||
response = MandayeResponse(response.code,
|
||||
response.msg,
|
||||
response.headers,
|
||||
response.read())
|
||||
return self.on_response(response)
|
||||
return self.on_response(start_response, response)
|
||||
|
||||
def on_response(self, start_response, response):
|
||||
'''response: an instance of MandayeResponse
|
||||
'''
|
||||
# TODO: Move the headers tratment
|
||||
for key, value in headers.items():
|
||||
for key, value in response.headers.items():
|
||||
if key == 'location':
|
||||
# TODO; move this in a default conf
|
||||
location = value.replace(self.config['remote_host'], self.env["HTTP_HOST"])
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
- https support
|
||||
- HTML filters support
|
||||
- split the code
|
||||
- fix multi cookie management
|
||||
- add log management
|
||||
- new configuration file
|
||||
- add user / password storage and recording
|
||||
|
87
pocs/poc1.py
87
pocs/poc1.py
|
@ -19,6 +19,17 @@ opener = poster.streaminghttp.register_openers()
|
|||
# TODO: create a true configuration file
|
||||
drop_headers = ['transfer-encoding']
|
||||
|
||||
config = {
|
||||
'sfd.local:8088':
|
||||
{
|
||||
'remote_host': 'www.sfdiabete.org',
|
||||
'ssl': False
|
||||
},
|
||||
'linuxfr.local:8088':
|
||||
{
|
||||
'remote_host': 'linuxfr.org',
|
||||
}
|
||||
}
|
||||
|
||||
class RpRedirectHandler(urllib2.HTTPRedirectHandler):
|
||||
|
||||
|
@ -36,6 +47,82 @@ class DefaultErrorHandler(urllib2.HTTPDefaultErrorHandler):
|
|||
return result
|
||||
|
||||
|
||||
class RequestApp(object):
|
||||
|
||||
def __init__(self, global_config):
|
||||
self.env = None
|
||||
self.global_config = config
|
||||
self.config = None
|
||||
|
||||
def __call__(self, env, start_response):
|
||||
""" """
|
||||
self.env = env
|
||||
local_host = env['HTTP_HOST']
|
||||
# TODO: manage auth and url mapping
|
||||
if self.global_config.has_key(local_host):
|
||||
self.config = self.global_config[local_host]
|
||||
return self.on_request(start_response)
|
||||
else:
|
||||
start_response('404 Not Found', [])
|
||||
return []
|
||||
|
||||
def on_request(self, start_response):
|
||||
# TODO: manage header and cookie modifications
|
||||
print "on_request"
|
||||
# Clean this lines
|
||||
if self.env.get('QUERY_STRING'):
|
||||
url = "http://" + self.config['remote_host'] + self.env['PATH_INFO'] + "?" + self.env['QUERY_STRING']
|
||||
else:
|
||||
url = "http://" + self.config['remote_host'] + self.env['PATH_INFO']
|
||||
print self.env['REQUEST_METHOD'] + " " + url
|
||||
if self.env['REQUEST_METHOD'] == 'POST':
|
||||
data = self.env['wsgi.input'].read()
|
||||
req = urllib2.Request(url, data,
|
||||
{'Content-Length': self.env['CONTENT_LENGTH'],
|
||||
'Content-Type': self.env['CONTENT_TYPE']})
|
||||
else:
|
||||
req = urllib2.Request(url)
|
||||
# Pass the browser headers to the request
|
||||
# TODO: move this in on_req header parser
|
||||
for name in (name for name in self.env if name.startswith('HTTP_')):
|
||||
value = self.env[name]
|
||||
if name == "HTTP_REFERER":
|
||||
referer = value.replace(self.env["HTTP_HOST"], self.config['remote_host'])
|
||||
req.add_header("Referer", referer)
|
||||
if name != "HTTP_HOST" and name != "HTTP_REFERER":
|
||||
name = name.split('HTTP_')[1].replace('_', '-')
|
||||
req.add_header(name, value)
|
||||
try:
|
||||
opener = urllib2.build_opener(RpRedirectHandler, DefaultErrorHandler)
|
||||
response = opener.open(req)
|
||||
except Exception:
|
||||
ex = sys.exc_info()[1]
|
||||
path = self.env['PATH_INFO']
|
||||
sys.stderr.write('error while reading %s:\n' % path)
|
||||
traceback.print_exc()
|
||||
tb = traceback.format_exc()
|
||||
start_response('502 Bad Gateway', [('Content-Type', 'text/html')])
|
||||
error_str = escape(str(ex) or ex.__class__.__name__ or 'Error')
|
||||
return ['<h1>%s</h1><h2>%s</h2><pre>%s</pre>' % (error_str, escape(path), escape(tb))]
|
||||
else:
|
||||
data = response.read()
|
||||
return self.on_response(start_response, response.code, response.msg, response.headers, data)
|
||||
|
||||
def on_response(self, start_response, code, status, headers, data):
|
||||
# TODO; use an response object
|
||||
print "on_response"
|
||||
for key, value in headers.items():
|
||||
if key == 'location':
|
||||
# TODO; move this in a default conf
|
||||
location = value.replace(self.config['remote_host'], self.env["HTTP_HOST"])
|
||||
headers[key] = location
|
||||
if key == 'set-cookie':
|
||||
# TODO : add cookie parser here
|
||||
pass
|
||||
if key in drop_headers:
|
||||
del headers[key]
|
||||
start_response('%d %s' % (code, status), headers.items())
|
||||
return [data]
|
||||
|
||||
|
||||
def serve(host,port):
|
||||
|
|
Reference in New Issue