1 """Wrapper for mod_wsgi, for use as a CherryPy HTTP server.
3 To autostart modwsgi, the "apache" executable or script must be
4 on your system path, or you must override the global APACHE_PATH.
5 On some platforms, "apache" may be called "apachectl" or "apache2ctl"--
6 create a symlink to them if needed.
12 ##1. Apache processes Range headers automatically; CherryPy's truncated
13 ## output is then truncated again by Apache. See test_core.testRanges.
14 ## This was worked around in http://www.cherrypy.org/changeset/1319.
15 2. Apache does not allow custom HTTP methods like CONNECT as per the spec.
16 See test_core.testHTTPMethods.
17 3. Max request header and body settings do not work with Apache.
18 ##4. Apache replaces status "reason phrases" automatically. For example,
19 ## CherryPy may set "304 Not modified" but Apache will write out
20 ## "304 Not Modified" (capital "M").
21 ##5. Apache does not allow custom error codes as per the spec.
22 ##6. Apache (or perhaps modpython, or modpython_gateway) unquotes %xx in the
23 ## Request-URI too early.
24 7. mod_wsgi will not read request bodies which use the "chunked"
25 transfer-coding (it passes REQUEST_CHUNKED_ERROR to ap_setup_client_block
26 instead of REQUEST_CHUNKED_DECHUNK, see Apache2's http_protocol.c and
27 mod_python's requestobject.c).
28 8. When responding with 204 No Content, mod_wsgi adds a Content-Length
30 9. When an error is raised, mod_wsgi has no facility for printing a
31 traceback as the response content (it's sent to the Apache log instead).
32 10. Startup and shutdown of Apache when running mod_wsgi seems slow.
36 curdir
= os
.path
.abspath(os
.path
.dirname(__file__
))
42 from cherrypy
.test
import helper
, webtest
45 def read_process(cmd
, args
=""):
46 pipein
, pipeout
= os
.popen4("%s %s" % (cmd
, args
))
48 firstline
= pipeout
.readline()
49 if (re
.search(r
"(not recognized|No such file|not found)", firstline
,
51 raise IOError('%s must be on your system path.' % cmd
)
52 output
= firstline
+ pipeout
.read()
58 if sys
.platform
== 'win32':
61 APACHE_PATH
= "apache"
63 CONF_PATH
= "test_mw.conf"
66 # Apache2 server conf file for testing CherryPy with modpython_gateway.
72 AllowEncodedSlashes On
73 LoadModule rewrite_module modules/mod_rewrite.so
75 RewriteMap escaping int:escape
77 LoadModule log_config_module modules/mod_log_config.so
78 LogFormat "%%h %%l %%u %%t \"%%r\" %%>s
%%b
\"%%{Referer}i
\" \"%%{User
-agent
}i
\"" combined
79 CustomLog "%(curdir)s/apache
.access
.log
" combined
80 ErrorLog "%(curdir)s/apache
.error
.log
"
83 LoadModule wsgi_module modules/mod_wsgi.so
84 LoadModule env_module modules/mod_env.so
86 WSGIScriptAlias / "%(curdir)s/modwsgi
.py
"
87 SetEnv testmod %(testmod)s
91 class ModWSGISupervisor(helper.Supervisor):
92 """Server Controller for ModWSGI and CherryPy."""
99 return "ModWSGI Server on
%s:%s" % (self.host, self.port)
101 def start(self, modulename):
103 if not os.path.isabs(mpconf):
104 mpconf = os.path.join(curdir, mpconf)
106 f = open(mpconf, 'wb')
108 output = (self.template %
109 {'port': self.port, 'testmod': modulename,
115 result = read_process(APACHE_PATH, "-k start
-f
%s" % mpconf)
119 # Make a request so mod_wsgi starts up our app.
120 # If we don't, concurrent initial requests will 404.
121 cherrypy._cpserver.wait_for_occupied_port("127.0.0.1", self.port)
122 webtest.openURL('/ihopetheresnodefault', port=self.port)
126 """Gracefully shutdown a server that is serving forever."""
127 read_process(APACHE_PATH, "-k stop
")
131 def application(environ, start_response):
136 modname = "cherrypy
.test
." + environ['testmod']
137 mod = __import__(modname, globals(), locals(), [''])
140 cherrypy.config.update({
141 "log
.error_file
": os.path.join(curdir, "test
.error
.log
"),
142 "log
.access_file
": os.path.join(curdir, "test
.access
.log
"),
143 "environment
": "test_suite
",
144 "engine
.SIGHUP
": None,
145 "engine
.SIGTERM
": None,
147 return cherrypy.tree(environ, start_response)