Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(177)

Side by Side Diff: third_party/cherrypy/_cpmodpy.py

Issue 9368042: Add CherryPy to third_party. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build/
Patch Set: '' Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/cherrypy/_cplogging.py ('k') | third_party/cherrypy/_cpnative_server.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 """Native adapter for serving CherryPy via mod_python
2
3 Basic usage:
4
5 ##########################################
6 # Application in a module called myapp.py
7 ##########################################
8
9 import cherrypy
10
11 class Root:
12 @cherrypy.expose
13 def index(self):
14 return 'Hi there, Ho there, Hey there'
15
16
17 # We will use this method from the mod_python configuration
18 # as the entry point to our application
19 def setup_server():
20 cherrypy.tree.mount(Root())
21 cherrypy.config.update({'environment': 'production',
22 'log.screen': False,
23 'show_tracebacks': False})
24
25 ##########################################
26 # mod_python settings for apache2
27 # This should reside in your httpd.conf
28 # or a file that will be loaded at
29 # apache startup
30 ##########################################
31
32 # Start
33 DocumentRoot "/"
34 Listen 8080
35 LoadModule python_module /usr/lib/apache2/modules/mod_python.so
36
37 <Location "/">
38 PythonPath "sys.path+['/path/to/my/application']"
39 SetHandler python-program
40 PythonHandler cherrypy._cpmodpy::handler
41 PythonOption cherrypy.setup myapp::setup_server
42 PythonDebug On
43 </Location>
44 # End
45
46 The actual path to your mod_python.so is dependent on your
47 environment. In this case we suppose a global mod_python
48 installation on a Linux distribution such as Ubuntu.
49
50 We do set the PythonPath configuration setting so that
51 your application can be found by from the user running
52 the apache2 instance. Of course if your application
53 resides in the global site-package this won't be needed.
54
55 Then restart apache2 and access http://127.0.0.1:8080
56 """
57
58 import logging
59 import sys
60
61 import cherrypy
62 from cherrypy._cpcompat import BytesIO, copyitems, ntob
63 from cherrypy._cperror import format_exc, bare_error
64 from cherrypy.lib import httputil
65
66
67 # ------------------------------ Request-handling
68
69
70
71 def setup(req):
72 from mod_python import apache
73
74 # Run any setup functions defined by a "PythonOption cherrypy.setup" directi ve.
75 options = req.get_options()
76 if 'cherrypy.setup' in options:
77 for function in options['cherrypy.setup'].split():
78 atoms = function.split('::', 1)
79 if len(atoms) == 1:
80 mod = __import__(atoms[0], globals(), locals())
81 else:
82 modname, fname = atoms
83 mod = __import__(modname, globals(), locals(), [fname])
84 func = getattr(mod, fname)
85 func()
86
87 cherrypy.config.update({'log.screen': False,
88 "tools.ignore_headers.on": True,
89 "tools.ignore_headers.headers": ['Range'],
90 })
91
92 engine = cherrypy.engine
93 if hasattr(engine, "signal_handler"):
94 engine.signal_handler.unsubscribe()
95 if hasattr(engine, "console_control_handler"):
96 engine.console_control_handler.unsubscribe()
97 engine.autoreload.unsubscribe()
98 cherrypy.server.unsubscribe()
99
100 def _log(msg, level):
101 newlevel = apache.APLOG_ERR
102 if logging.DEBUG >= level:
103 newlevel = apache.APLOG_DEBUG
104 elif logging.INFO >= level:
105 newlevel = apache.APLOG_INFO
106 elif logging.WARNING >= level:
107 newlevel = apache.APLOG_WARNING
108 # On Windows, req.server is required or the msg will vanish. See
109 # http://www.modpython.org/pipermail/mod_python/2003-October/014291.html .
110 # Also, "When server is not specified...LogLevel does not apply..."
111 apache.log_error(msg, newlevel, req.server)
112 engine.subscribe('log', _log)
113
114 engine.start()
115
116 def cherrypy_cleanup(data):
117 engine.exit()
118 try:
119 # apache.register_cleanup wasn't available until 3.1.4.
120 apache.register_cleanup(cherrypy_cleanup)
121 except AttributeError:
122 req.server.register_cleanup(req, cherrypy_cleanup)
123
124
125 class _ReadOnlyRequest:
126 expose = ('read', 'readline', 'readlines')
127 def __init__(self, req):
128 for method in self.expose:
129 self.__dict__[method] = getattr(req, method)
130
131
132 recursive = False
133
134 _isSetUp = False
135 def handler(req):
136 from mod_python import apache
137 try:
138 global _isSetUp
139 if not _isSetUp:
140 setup(req)
141 _isSetUp = True
142
143 # Obtain a Request object from CherryPy
144 local = req.connection.local_addr
145 local = httputil.Host(local[0], local[1], req.connection.local_host or " ")
146 remote = req.connection.remote_addr
147 remote = httputil.Host(remote[0], remote[1], req.connection.remote_host or "")
148
149 scheme = req.parsed_uri[0] or 'http'
150 req.get_basic_auth_pw()
151
152 try:
153 # apache.mpm_query only became available in mod_python 3.1
154 q = apache.mpm_query
155 threaded = q(apache.AP_MPMQ_IS_THREADED)
156 forked = q(apache.AP_MPMQ_IS_FORKED)
157 except AttributeError:
158 bad_value = ("You must provide a PythonOption '%s', "
159 "either 'on' or 'off', when running a version "
160 "of mod_python < 3.1")
161
162 threaded = options.get('multithread', '').lower()
163 if threaded == 'on':
164 threaded = True
165 elif threaded == 'off':
166 threaded = False
167 else:
168 raise ValueError(bad_value % "multithread")
169
170 forked = options.get('multiprocess', '').lower()
171 if forked == 'on':
172 forked = True
173 elif forked == 'off':
174 forked = False
175 else:
176 raise ValueError(bad_value % "multiprocess")
177
178 sn = cherrypy.tree.script_name(req.uri or "/")
179 if sn is None:
180 send_response(req, '404 Not Found', [], '')
181 else:
182 app = cherrypy.tree.apps[sn]
183 method = req.method
184 path = req.uri
185 qs = req.args or ""
186 reqproto = req.protocol
187 headers = copyitems(req.headers_in)
188 rfile = _ReadOnlyRequest(req)
189 prev = None
190
191 try:
192 redirections = []
193 while True:
194 request, response = app.get_serving(local, remote, scheme,
195 "HTTP/1.1")
196 request.login = req.user
197 request.multithread = bool(threaded)
198 request.multiprocess = bool(forked)
199 request.app = app
200 request.prev = prev
201
202 # Run the CherryPy Request object and obtain the response
203 try:
204 request.run(method, path, qs, reqproto, headers, rfile)
205 break
206 except cherrypy.InternalRedirect:
207 ir = sys.exc_info()[1]
208 app.release_serving()
209 prev = request
210
211 if not recursive:
212 if ir.path in redirections:
213 raise RuntimeError("InternalRedirector visited t he "
214 "same URL twice: %r" % ir.pat h)
215 else:
216 # Add the *previous* path_info + qs to redirecti ons.
217 if qs:
218 qs = "?" + qs
219 redirections.append(sn + path + qs)
220
221 # Munge environment and try again.
222 method = "GET"
223 path = ir.path
224 qs = ir.query_string
225 rfile = BytesIO()
226
227 send_response(req, response.output_status, response.header_list,
228 response.body, response.stream)
229 finally:
230 app.release_serving()
231 except:
232 tb = format_exc()
233 cherrypy.log(tb, 'MOD_PYTHON', severity=logging.ERROR)
234 s, h, b = bare_error()
235 send_response(req, s, h, b)
236 return apache.OK
237
238
239 def send_response(req, status, headers, body, stream=False):
240 # Set response status
241 req.status = int(status[:3])
242
243 # Set response headers
244 req.content_type = "text/plain"
245 for header, value in headers:
246 if header.lower() == 'content-type':
247 req.content_type = value
248 continue
249 req.headers_out.add(header, value)
250
251 if stream:
252 # Flush now so the status and headers are sent immediately.
253 req.flush()
254
255 # Set response body
256 if isinstance(body, basestring):
257 req.write(body)
258 else:
259 for seg in body:
260 req.write(seg)
261
262
263
264 # --------------- Startup tools for CherryPy + mod_python --------------- #
265
266
267 import os
268 import re
269 try:
270 import subprocess
271 def popen(fullcmd):
272 p = subprocess.Popen(fullcmd, shell=True,
273 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
274 close_fds=True)
275 return p.stdout
276 except ImportError:
277 def popen(fullcmd):
278 pipein, pipeout = os.popen4(fullcmd)
279 return pipeout
280
281
282 def read_process(cmd, args=""):
283 fullcmd = "%s %s" % (cmd, args)
284 pipeout = popen(fullcmd)
285 try:
286 firstline = pipeout.readline()
287 if (re.search(ntob("(not recognized|No such file|not found)"), firstline ,
288 re.IGNORECASE)):
289 raise IOError('%s must be on your system path.' % cmd)
290 output = firstline + pipeout.read()
291 finally:
292 pipeout.close()
293 return output
294
295
296 class ModPythonServer(object):
297
298 template = """
299 # Apache2 server configuration file for running CherryPy with mod_python.
300
301 DocumentRoot "/"
302 Listen %(port)s
303 LoadModule python_module modules/mod_python.so
304
305 <Location %(loc)s>
306 SetHandler python-program
307 PythonHandler %(handler)s
308 PythonDebug On
309 %(opts)s
310 </Location>
311 """
312
313 def __init__(self, loc="/", port=80, opts=None, apache_path="apache",
314 handler="cherrypy._cpmodpy::handler"):
315 self.loc = loc
316 self.port = port
317 self.opts = opts
318 self.apache_path = apache_path
319 self.handler = handler
320
321 def start(self):
322 opts = "".join([" PythonOption %s %s\n" % (k, v)
323 for k, v in self.opts])
324 conf_data = self.template % {"port": self.port,
325 "loc": self.loc,
326 "opts": opts,
327 "handler": self.handler,
328 }
329
330 mpconf = os.path.join(os.path.dirname(__file__), "cpmodpy.conf")
331 f = open(mpconf, 'wb')
332 try:
333 f.write(conf_data)
334 finally:
335 f.close()
336
337 response = read_process(self.apache_path, "-k start -f %s" % mpconf)
338 self.ready = True
339 return response
340
341 def stop(self):
342 os.popen("apache -k stop")
343 self.ready = False
344
OLDNEW
« no previous file with comments | « third_party/cherrypy/_cplogging.py ('k') | third_party/cherrypy/_cpnative_server.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698