Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/cherrypy/test/modwsgi.py
diff options
context:
space:
mode:
Diffstat (limited to 'cherrypy/test/modwsgi.py')
-rwxr-xr-xcherrypy/test/modwsgi.py148
1 files changed, 148 insertions, 0 deletions
diff --git a/cherrypy/test/modwsgi.py b/cherrypy/test/modwsgi.py
new file mode 100755
index 0000000..309a541
--- /dev/null
+++ b/cherrypy/test/modwsgi.py
@@ -0,0 +1,148 @@
+"""Wrapper for mod_wsgi, for use as a CherryPy HTTP server.
+
+To autostart modwsgi, the "apache" executable or script must be
+on your system path, or you must override the global APACHE_PATH.
+On some platforms, "apache" may be called "apachectl" or "apache2ctl"--
+create a symlink to them if needed.
+
+
+KNOWN BUGS
+==========
+
+##1. Apache processes Range headers automatically; CherryPy's truncated
+## output is then truncated again by Apache. See test_core.testRanges.
+## This was worked around in http://www.cherrypy.org/changeset/1319.
+2. Apache does not allow custom HTTP methods like CONNECT as per the spec.
+ See test_core.testHTTPMethods.
+3. Max request header and body settings do not work with Apache.
+##4. Apache replaces status "reason phrases" automatically. For example,
+## CherryPy may set "304 Not modified" but Apache will write out
+## "304 Not Modified" (capital "M").
+##5. Apache does not allow custom error codes as per the spec.
+##6. Apache (or perhaps modpython, or modpython_gateway) unquotes %xx in the
+## Request-URI too early.
+7. mod_wsgi will not read request bodies which use the "chunked"
+ transfer-coding (it passes REQUEST_CHUNKED_ERROR to ap_setup_client_block
+ instead of REQUEST_CHUNKED_DECHUNK, see Apache2's http_protocol.c and
+ mod_python's requestobject.c).
+8. When responding with 204 No Content, mod_wsgi adds a Content-Length
+ header for you.
+9. When an error is raised, mod_wsgi has no facility for printing a
+ traceback as the response content (it's sent to the Apache log instead).
+10. Startup and shutdown of Apache when running mod_wsgi seems slow.
+"""
+
+import os
+curdir = os.path.abspath(os.path.dirname(__file__))
+import re
+import sys
+import time
+
+import cherrypy
+from cherrypy.test import helper, webtest
+
+
+def read_process(cmd, args=""):
+ pipein, pipeout = os.popen4("%s %s" % (cmd, args))
+ try:
+ firstline = pipeout.readline()
+ if (re.search(r"(not recognized|No such file|not found)", firstline,
+ re.IGNORECASE)):
+ raise IOError('%s must be on your system path.' % cmd)
+ output = firstline + pipeout.read()
+ finally:
+ pipeout.close()
+ return output
+
+
+if sys.platform == 'win32':
+ APACHE_PATH = "httpd"
+else:
+ APACHE_PATH = "apache"
+
+CONF_PATH = "test_mw.conf"
+
+conf_modwsgi = r"""
+# Apache2 server conf file for testing CherryPy with modpython_gateway.
+
+ServerName 127.0.0.1
+DocumentRoot "/"
+Listen %(port)s
+
+AllowEncodedSlashes On
+LoadModule rewrite_module modules/mod_rewrite.so
+RewriteEngine on
+RewriteMap escaping int:escape
+
+LoadModule log_config_module modules/mod_log_config.so
+LogFormat "%%h %%l %%u %%t \"%%r\" %%>s %%b \"%%{Referer}i\" \"%%{User-agent}i\"" combined
+CustomLog "%(curdir)s/apache.access.log" combined
+ErrorLog "%(curdir)s/apache.error.log"
+LogLevel debug
+
+LoadModule wsgi_module modules/mod_wsgi.so
+LoadModule env_module modules/mod_env.so
+
+WSGIScriptAlias / "%(curdir)s/modwsgi.py"
+SetEnv testmod %(testmod)s
+"""
+
+
+class ModWSGISupervisor(helper.Supervisor):
+ """Server Controller for ModWSGI and CherryPy."""
+
+ using_apache = True
+ using_wsgi = True
+ template=conf_modwsgi
+
+ def __str__(self):
+ return "ModWSGI Server on %s:%s" % (self.host, self.port)
+
+ def start(self, modulename):
+ mpconf = CONF_PATH
+ if not os.path.isabs(mpconf):
+ mpconf = os.path.join(curdir, mpconf)
+
+ f = open(mpconf, 'wb')
+ try:
+ output = (self.template %
+ {'port': self.port, 'testmod': modulename,
+ 'curdir': curdir})
+ f.write(output)
+ finally:
+ f.close()
+
+ result = read_process(APACHE_PATH, "-k start -f %s" % mpconf)
+ if result:
+ print(result)
+
+ # Make a request so mod_wsgi starts up our app.
+ # If we don't, concurrent initial requests will 404.
+ cherrypy._cpserver.wait_for_occupied_port("127.0.0.1", self.port)
+ webtest.openURL('/ihopetheresnodefault', port=self.port)
+ time.sleep(1)
+
+ def stop(self):
+ """Gracefully shutdown a server that is serving forever."""
+ read_process(APACHE_PATH, "-k stop")
+
+
+loaded = False
+def application(environ, start_response):
+ import cherrypy
+ global loaded
+ if not loaded:
+ loaded = True
+ modname = "cherrypy.test." + environ['testmod']
+ mod = __import__(modname, globals(), locals(), [''])
+ mod.setup_server()
+
+ cherrypy.config.update({
+ "log.error_file": os.path.join(curdir, "test.error.log"),
+ "log.access_file": os.path.join(curdir, "test.access.log"),
+ "environment": "test_suite",
+ "engine.SIGHUP": None,
+ "engine.SIGTERM": None,
+ })
+ return cherrypy.tree(environ, start_response)
+