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

194 lines
7.3 KiB
Python

import Cookie
import config
import urllib
import urllib2
import poster.streaminghttp
import random
import re
import os
import sys
import time
import traceback
from beaker.middleware import SessionMiddleware
from cgi import escape
from md5 import md5
from static import Cling
import mandaye
from mandaye.config import debug
from mandaye.dispatcher import Dispatcher
from mandaye.log import logger, format_logging_handlers
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())
logger.info('Mandaye POST %s' % url)
logger.debug('POST content %s' % request.msg)
else:
req = urllib2.Request(url, headers=request.headers.getheaders())
logger.info('Mandaye GET %s' % url)
# 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.get(cookie.name) == cookie.value:
continue
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._getdate(cookie.expires-time.time())
if cookie.domain.startswith('.'):
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
if env.has_key('HTTP_X_FORWARDED_SCHEME'):
self.env['mandaye.scheme'] = env['HTTP_X_FORWARDED_SCHEME']
else:
self.env['mandaye.scheme'] = env['wsgi.url_scheme']
self.env['mandaye.uuid'] = self._get_uuid()
self.dispatcher = None
local_host = env['HTTP_HOST']
path_info = env['PATH_INFO']
format_logging_handlers(self.env['mandaye.uuid'])
logger.info("Client %s - %s %s://%s%s" %\
(self.env['REMOTE_ADDR'], self.env['REQUEST_METHOD'],
self.env['wsgi.url_scheme'], self.env['HTTP_HOST'],
self.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_uuid(self):
id_str = "%f%s%f%s" % (
time.time(),
id({}),
random.random(),
os.getpid
)
return md5(md5(id_str).hexdigest()).hexdigest()
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
target = self.dispatcher.get_target_url()
return HTTPRequest(cookies, headers, self.env['REQUEST_METHOD'], msg, target)
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"))
if not request.target:
response = self.dispatcher.get_response(request)
else:
response = get_response(self.env, request, request.target)
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]