188 lines
6.9 KiB
Python
188 lines
6.9 KiB
Python
|
|
# gevent patching
|
|
#from gevent import monkey
|
|
#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, WSGIHandler
|
|
from static import Cling
|
|
|
|
from mandaye.config import debug
|
|
from mandaye.dispatcher import Dispatcher
|
|
from mandaye.handlers.default import MandayeRedirectHandler, MandayeErrorHandler
|
|
from mandaye.http import HTTPHeader, HTTPRequest, HTTPResponse
|
|
from mandaye.response import _404, _502, _500
|
|
from mandaye.db import sql_session
|
|
|
|
# Init poster
|
|
opener = poster.streaminghttp.register_openers()
|
|
|
|
def get_response(env, request, url, cookiejar=None):
|
|
""" request: Mandaye Request
|
|
url: the target url
|
|
"""
|
|
url = re.sub('(?<!:)/+', '/', url)
|
|
if request.req_method == 'POST':
|
|
req = urllib2.Request(url, request.msg, request.headers.getheaders())
|
|
else:
|
|
req = urllib2.Request(url, headers=request.headers.getheaders())
|
|
# Load the cookies
|
|
if request.cookies:
|
|
req.add_header('cookie', request.cookies.output(attrs=[], sep=';', header=''))
|
|
try:
|
|
if debug:
|
|
opener = urllib2.build_opener(MandayeErrorHandler, MandayeRedirectHandler,
|
|
urllib2.HTTPSHandler(debuglevel=1), urllib2.HTTPHandler(debuglevel=1))
|
|
else:
|
|
opener = urllib2.build_opener(MandayeErrorHandler, MandayeRedirectHandler)
|
|
if cookiejar != None:
|
|
opener.add_handler(urllib2.HTTPCookieProcessor(cookiejar))
|
|
resp = opener.open(req)
|
|
except Exception, e:
|
|
response = _502(env['PATH_INFO'], req.get_host(), e)
|
|
else:
|
|
response = HTTPResponse()
|
|
response.load_from_urllib(resp)
|
|
if cookiejar:
|
|
response.cookies = Cookie.BaseCookie()
|
|
for cookie in cookiejar:
|
|
if response.cookies.has_key(cookie.name):
|
|
del response.cookies[cookie.name]
|
|
response.cookies[cookie.name] = cookie.value
|
|
if cookie.expires:
|
|
response.cookies[cookie.name]['expires'] = cookie.expires
|
|
if cookie.domain:
|
|
response.cookies[cookie.name]['domain'] = cookie.domain
|
|
if cookie.path:
|
|
response.cookies[cookie.name]['path'] = cookie.path
|
|
# TODO: add the other RFC 2109 cookie values
|
|
resp.close()
|
|
return response
|
|
|
|
|
|
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
|
|
"""
|
|
response = []
|
|
try:
|
|
self.env = env
|
|
self.env['mandaye.scheme'] = env['wsgi.url_scheme']
|
|
self.dispatcher = None
|
|
local_host = env['HTTP_HOST']
|
|
path_info = env['PATH_INFO']
|
|
if config.hosts.has_key(local_host):
|
|
for mapper in config.hosts[local_host]:
|
|
if re.match(mapper.get('path'), path_info):
|
|
if mapper.get('force_ssl'):
|
|
self.env['mandaye.scheme'] = 'https'
|
|
if mapper.has_key('target'):
|
|
self.dispatcher = Dispatcher(self.env, mapper.get('target'),
|
|
mapper.get('mapping'))
|
|
elif mapper.has_key('static'):
|
|
env['PATH_INFO'] = re.sub('^' + mapper.get('path'), '',
|
|
env['PATH_INFO'])
|
|
response = Cling(mapper.get('static')).__call__(env, start_response)
|
|
if not response:
|
|
if self.dispatcher:
|
|
response = self.on_request(start_response)
|
|
else:
|
|
response = self.on_response(start_response, _404(env['PATH_INFO']))
|
|
sql_session.commit()
|
|
except Exception, e:
|
|
sql_session.rollback()
|
|
response = self.on_response(start_response, _500(env['PATH_INFO'], "Unhandled exception",
|
|
exception=e, env=env))
|
|
finally:
|
|
sql_session.close()
|
|
return response
|
|
|
|
|
|
def _get_request(self):
|
|
""" Return a Mandaye HTTP Request
|
|
"""
|
|
headers = HTTPHeader()
|
|
if self.env.get('CONTENT_LENGTH'):
|
|
headers.addheader('Content-Length', self.env['CONTENT_LENGTH'])
|
|
if self.env.get('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, self.env['REQUEST_METHOD'], msg)
|
|
|
|
def on_request(self, start_response):
|
|
request = self._get_request()
|
|
# Calling the dispatcher hook for the request
|
|
request = self.dispatcher.mod_request(request)
|
|
if not request:
|
|
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(request))
|
|
response = get_response(self.env, request, url)
|
|
response = self.dispatcher.mod_response(request, response)
|
|
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.reason),
|
|
response.headers.items())
|
|
return [response.msg]
|
|
|
|
class ServerHandler(WSGIHandler):
|
|
|
|
def log_request(self):
|
|
logging.info(self.format_request())
|
|
|
|
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,
|
|
handler_class=ServerHandler)
|
|
else:
|
|
s = WSGIServer((config.host, config.port), wsgi_app,
|
|
handler_class=ServerHandler)
|
|
try:
|
|
s.serve_forever()
|
|
except KeyboardInterrupt:
|
|
s.stop()
|
|
|