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

131 lines
4.6 KiB
Python

from gevent import monkey
# gevent patching
monkey.patch_all()
import Cookie
import config
import logging
import urllib
import urllib2
import re
import sys
import traceback
import poster.streaminghttp
from beaker.middleware import SessionMiddleware
from cgi import escape
from gevent.pywsgi import WSGIServer
from mandaye.handlers.default import MandayeRedirectHandler, MandayeErrorHandler
from mandaye.http import HTTPHeader, HTTPRequest, HTTPResponse
from mandaye.response import _404, _502
# Init poster
opener = poster.streaminghttp.register_openers()
class MandayeApp(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:
self.dispatcher.init(env)
return self.on_request(start_response)
else:
return self.on_response(start_response, _404(env['PATH_INFO']))
def _get_dispatcher(self, local_host, path_info):
""" return the right dispatcher
"""
if config.hosts.has_key(local_host):
for mapper in config.hosts[local_host]:
if re.match(mapper[0], path_info):
return mapper[1]
return None
def _get_request(self):
""" Return a Mandaye HTTP Request
"""
headers = HTTPHeader()
if self.env.has_key('CONTENT_LENGTH'):
headers.addheader('Content-Length', self.env['CONTENT_LENGTH'])
if self.env.has_key('CONTENT_TYPE'):
headers.addheader('Content-Type', self.env['CONTENT_TYPE'])
for name in (name for name in self.env if name.startswith('HTTP_')):
value = self.env[name]
if name != "HTTP_HOST" and name != "HTTP_COOKIE":
name = name.split('HTTP_')[1].replace('_', '-')
headers.addheader(name, value)
if self.env.has_key('HTTP_COOKIE'):
cookies = Cookie.BaseCookie(self.env['HTTP_COOKIE'])
else:
cookies = Cookie.BaseCookie()
if self.env['REQUEST_METHOD'] == 'POST':
msg = self.env['wsgi.input']
else:
msg = None
return HTTPRequest(cookies, headers, msg)
def on_request(self, start_response):
mrequest = self._get_request()
# Calling the dispatcher hook for the request
mrequest = self.dispatcher.mod_request(mrequest)
if not mrequest:
return self.on_response(start_response,
_500(self.env["PATH_INFO"], "Empty request"))
url = self.dispatcher.get_target_url()
if not url:
return self.on_response(start_response,
self.dispatcher.get_response(mrequest))
if self.env['REQUEST_METHOD'] == 'POST':
data = self.env['wsgi.input'].read()
req = urllib2.Request(url, data, mrequest.headers.getheaders())
else:
req = urllib2.Request(url, headers=mrequest.headers.getheaders())
# Load the cookies
req.add_header('cookie', mrequest.cookies.output(sep=',', header=''))
try:
opener = urllib2.build_opener(MandayeErrorHandler, MandayeRedirectHandler)
response = opener.open(req)
except Exception, e:
response = _502(self.env['PATH_INFO'], req.get_host(), e)
return self.on_response(start_response, response)
else:
mresponse = HTTPResponse()
mresponse.load_from_urllib(response)
response = self.dispatcher.mod_response(mrequest, mresponse)
return self.on_response(start_response, response)
def on_response(self, start_response, response):
""" start_response: wsgi start_response
response: an instance of HTTPResponse """
response.headers.addsetcookies(response.cookies)
start_response('%d %s' % (response.code, response.status),
response.headers.items())
return [response.msg]
def serve():
"""Convenience function to immediately start a server instance."""
wsgi_app = SessionMiddleware(MandayeApp(), config.session_opts)
if config.ssl:
s = WSGIServer((config.host, config.port), wsgi_app,
keyfile=config.keyfile, certfile=config.certfile)
else:
s = WSGIServer((config.host, config.port), wsgi_app)
try:
s.serve_forever()
except KeyboardInterrupt:
s.stop()