This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
mandaye/mandaye/server.py

112 lines
4.0 KiB
Python

# gevent patching
from gevent import monkey
monkey.patch_all()
import config
import urllib
import urllib2
import re
import poster.streaminghttp
from gevent.pywsgi import WSGIServer
from response import _404, _502
from response import MandayeResponse
# Init poster
opener = poster.streaminghttp.register_openers()
class RequestApp(object):
def __init__(self):
self.env = None
self.dispatcher = None
def __call__(self, env, start_response):
""" called by the WSGI server
env: standard WSGI env
start_response: stanard WSGI / CGI function
"""
self.env = env
self.dispatcher = self._get_dispatcher(env['HTTP_HOST'], env['PATH_INFO'])
if self.dispatcher:
return self.on_request(start_response)
else:
return self.on_response(start_response, _404)
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]:
if re.match(url[0], path_info):
return url[1]
return None
def on_request(self, start_response):
# TODO: manage header and cookie modifications
# Clean this lines
url = self.dispatcher.get_target(self.env['PATH_INFO'], self.env['QUERY_STRING'])
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()
response = _502
_502.content = '<h1>%s</h1><h2>%s</h2><pre>%s</pre>' % \
(error_str, escape(path), escape(tb))
_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)
def on_response(self, start_response, response):
'''response: an instance of MandayeResponse
'''
# TODO: Move the headers tratment
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
start_response('%d %s' % (response.code, response.status), response.headers.items())
return [response.content]
def serve():
"""Convenience function to immediately start a server instance."""
if config.ssl:
s = WSGIServer((config.host, config.port), RequestApp(),
keyfile=config.keyfile, certfile=config.certfile)
else:
s = WSGIServer((config.host, config.port), RequestApp())
s.serve_forever()