Commit c30fca1e authored by Lennart Regebro's avatar Lennart Regebro

A first attempt to tear the ZServer away from the ZPublisher, and put a wsgi

interface inbetween.
parent 88301ada
......@@ -43,7 +43,7 @@ The following code should be at the top of every test module:
if __name__ == '__main__':
framework()
$Id:$
$Id$
"""
__version__ = '0.2.4'
......
......@@ -12,7 +12,7 @@
##############################################################################
"""Placeless setup tests
$Id:$
$Id$
"""
import os, sys
......
......@@ -12,7 +12,7 @@
##############################################################################
"""Skeleton ZopeTestCase
$Id:$
$Id$
"""
import os, sys
......
......@@ -13,7 +13,7 @@
"""Parts of ZServer support are in this module so they can
be imported more selectively.
$Id: threadutils.py,v 1.6 2004/08/19 15:31:26 shh42 Exp $
$Id$
"""
from threading import Thread
......
......@@ -43,7 +43,7 @@ The following code should be at the top of every test module:
if __name__ == '__main__':
framework()
$Id:$
$Id$
"""
__version__ = '0.2.4'
......
......@@ -12,7 +12,7 @@
##############################################################################
"""Test for auth_header
$Id: testAuthHeaderTest.py,v 1.2 2005/03/26 18:07:08 shh42 Exp $
$Id$
"""
import os, sys
......
......@@ -12,7 +12,7 @@
##############################################################################
"""Example doctest
$Id: testWarningsTest.py,v 1.2 2005/03/26 18:07:08 shh42 Exp $
$Id$
"""
import os, sys
......
......@@ -12,7 +12,7 @@
##############################################################################
"""Example Zope doctest
$Id: testZopeDocTest.py,v 1.2 2005/03/26 18:07:08 shh42 Exp $
$Id$
"""
import os, sys
......
......@@ -1484,12 +1484,12 @@ def parse_cookie(text,
else:
# Broken Cookie without = nor value.
broken_p = paramlessre.match(text)
if broken_p:
l = len(broken_p.group(1))
name = broken_p.group(2)
value = ''
broken_p = paramlessre.match(text)
if broken_p:
l = len(broken_p.group(1))
name = broken_p.group(2)
value = ''
else:
return result
......
......@@ -21,7 +21,6 @@ from Request import Request
from maybe_lock import allocate_lock
from mapply import mapply
from zExceptions import Redirect
from zope.app.publication.browser import setDefaultSkin
class Retry(Exception):
"""Raise this to retry a request
......@@ -57,7 +56,7 @@ def set_default_debug_mode(debug_mode):
def set_default_authentication_realm(realm):
global _default_realm
_default_realm = realm
_default_realm = realm
def publish(request, module_name, after_list, debug=0,
# Optimize:
......@@ -169,10 +168,122 @@ def publish(request, module_name, after_list, debug=0,
transactions_manager.abort()
raise
from HTTPRequest import HTTPRequest
from ZServer.HTTPResponse import make_response
class WSGIPublisherApplication(object):
"""A WSGI application implementation for the zope publisher
Instances of this class can be used as a WSGI application object.
The class relies on a properly initialized request factory.
"""
#implements(interfaces.IWSGIApplication)
def __init__(self, response):
self.response = response
def __call__(self, environ, start_response):
"""See zope.app.wsgi.interfaces.IWSGIApplication"""
from ZServer.HTTPResponse import ZServerHTTPResponse, is_proxying_match, proxying_connection_re
from ZServer.medusa import http_server
from cStringIO import StringIO
response = ZServerHTTPResponse(stdout=environ['wsgi.output'], stderr=StringIO())
response._http_version = environ['SERVER_PROTOCOL'].split('/')[1]
response._http_connection = environ['CONNECTION_TYPE']
response._server_version = environ['SERVER_SOFTWARE']
request = HTTPRequest(environ['wsgi.input'], environ, response)
# Let's support post-mortem debugging
handle_errors = environ.get('wsgi.handleErrors', True)
try:
response = publish(request, 'Zope2', after_list=[None],
debug=handle_errors)
except SystemExit, v:
must_die=sys.exc_info()
request.response.exception(must_die)
except ImportError, v:
if isinstance(v, tuple) and len(v)==3: must_die=v
elif hasattr(sys, 'exc_info'): must_die=sys.exc_info()
else: must_die = SystemExit, v, sys.exc_info()[2]
request.response.exception(1, v)
except:
request.response.exception()
status=response.getStatus()
if response:
# Start the WSGI server response
start_response(response.getHeader('status'),
response.headers.items())
result=str(response)
# Return the result body iterable.
request.close()
#response._finish(0)
return (result,)
def fakeWrite(body):
raise NotImplementedError(
"Zope 2's HTTP Server does not support the WSGI write() function.")
def publish_module_standard(module_name,
stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr,
environ=os.environ, debug=0, request=None, response=None):
# The WSGI way!
def wsgi_start_response(status,response_headers,exc_info=None):
# I don't understand what to do here. Start writing? At what?
return fakeWrite
must_die=0
status=200
after_list=[None]
if request is None:
env = environ.copy()
else:
env = request
env['wsgi.input'] = sys.stdin
env['wsgi.errors'] = sys.stderr
env['wsgi.version'] = (1,0)
env['wsgi.multithread'] = True
env['wsgi.multiprocess'] = True
env['wsgi.run_once'] = True
env['wsgi.url_scheme'] = env['SERVER_PROTOCOL'].split('/')[0]
if not env.has_key('wsgi.output'):
env['wsgi.output'] = stdout
application = WSGIPublisherApplication(None)
body = application(env, wsgi_start_response)
env['wsgi.output'].write(body[0])
env['wsgi.output'].close()
# The module defined a post-access function, call it
if after_list[0] is not None: after_list[0]()
if must_die:
# Try to turn exception value into an exit code.
try:
if hasattr(must_die[1], 'code'):
code = must_die[1].code
else: code = int(must_die[1])
except:
code = must_die[1] and 1 or 0
if hasattr(request.response, '_requestShutdown'):
request.response._requestShutdown(code)
try: raise must_die[0], must_die[1], must_die[2]
finally: must_die=None
return status
def publish_module_standard_old(module_name,
stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr,
environ=os.environ, debug=0, request=None, response=None):
must_die=0
status=200
after_list=[None]
......
......@@ -194,7 +194,7 @@ class ZServerHTTPResponse(HTTPResponse):
_retried_response = None
def _finish(self):
def _finish(self, close_output=1):
if self._retried_response:
try:
self._retried_response._finish()
......@@ -209,7 +209,8 @@ class ZServerHTTPResponse(HTTPResponse):
self._tempfile=None
stdout.finish(self)
stdout.close()
if close_output:
stdout.close()
self.stdout=None # need to break cycle?
self._request=None
......@@ -318,7 +319,6 @@ proxying_connection_re = re.compile ('Proxy-Connection: (.*)', re.IGNORECASE)
def make_response(request, headers):
"Simple http response factory"
# should this be integrated into the HTTPResponse constructor?
response=ZServerHTTPResponse(stdout=ChannelPipe(request), stderr=StringIO())
response._http_version=request.version
if request.version=='1.0' and is_proxying_match(request.request):
......
......@@ -261,13 +261,31 @@ class zhttp_handler:
s=0
DebugLogger.log('I', id(request), s)
#import pdb;pdb.set_trace()
env=self.get_environment(request)
zresponse=make_response(request,env)
if self._force_connection_close:
zresponse._http_connection = 'close'
zrequest=HTTPRequest(sin, env, zresponse)
from HTTPResponse import ChannelPipe, is_proxying_match, proxying_connection_re
env['wsgi.output'] = ChannelPipe(request)
version = request.version
if version=='1.0' and is_proxying_match(request.request):
# a request that was made as if this zope was an http 1.0 proxy.
# that means we have to use some slightly different http
# headers to manage persistent connections.
connection_re = proxying_connection_re
else:
# a normal http request
connection_re = CONNECTION
env['http_connection'] = get_header(connection_re,
request.header).lower()
env['server_version']=request.channel.server.SERVER_IDENT
#zresponse=make_response(request,env)
#if self._force_connection_close:
#zresponse._http_connection = 'close'
#zrequest=HTTPRequest(sin, env, zresponse)
request.channel.current_request=None
request.channel.queue.append((self.module_name, zrequest, zresponse))
request.channel.queue.append((self.module_name, env, None))
request.channel.work()
def status(self):
......
......@@ -22,5 +22,5 @@ class ZServerPublisher:
request=request,
response=response)
finally:
response._finish()
#response._finish()
request=response=None
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment