comparison mercurial/hgweb/wsgicgi.py @ 2506:d0db3462d568

This patch make several WSGI related alterations. First, it changes the server to be almost a generic WSGI server. Second, it changes request.py to have wsgiapplication and _wsgirequest. wsgiapplication is a class that creates _wsgirequests when called by a WSGI compliant server. It needs to know whether or not it should create hgwebdir or hgweb requests. Lastly, wsgicgi.py is added, and the CGI scripts are altered to use it to launch wsgiapplications in a WSGI compliant way. As a side effect, all the keepalive code has been removed from request.py. This code needs to be moved so that it is exclusively in server.py
author Eric Hopper <hopper@omnifarious.org>
date Tue, 27 Jun 2006 00:09:33 -0700
parents
children 1120302009d7
comparison
equal deleted inserted replaced
2505:01b856927970 2506:d0db3462d568
1 # hgweb/wsgicgi.py - CGI->WSGI translator
2 #
3 # Copyright 2006 Eric Hopper <hopper@omnifarious.org>
4 #
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
7 #
8 # This was originally copied from the public domain code at
9 # http://www.python.org/dev/peps/pep-0333/#the-server-gateway-side
10
11 import os, sys
12
13 def launch(application):
14
15 environ = dict(os.environ.items())
16 environ['wsgi.input'] = sys.stdin
17 environ['wsgi.errors'] = sys.stderr
18 environ['wsgi.version'] = (1,0)
19 environ['wsgi.multithread'] = False
20 environ['wsgi.multiprocess'] = True
21 environ['wsgi.run_once'] = True
22
23 if environ.get('HTTPS','off') in ('on','1'):
24 environ['wsgi.url_scheme'] = 'https'
25 else:
26 environ['wsgi.url_scheme'] = 'http'
27
28 headers_set = []
29 headers_sent = []
30
31 def write(data):
32 if not headers_set:
33 raise AssertionError("write() before start_response()")
34
35 elif not headers_sent:
36 # Before the first output, send the stored headers
37 status, response_headers = headers_sent[:] = headers_set
38 sys.stdout.write('Status: %s\r\n' % status)
39 for header in response_headers:
40 sys.stdout.write('%s: %s\r\n' % header)
41 sys.stdout.write('\r\n')
42
43 sys.stdout.write(data)
44 sys.stdout.flush()
45
46 def start_response(status,response_headers,exc_info=None):
47 if exc_info:
48 try:
49 if headers_sent:
50 # Re-raise original exception if headers sent
51 raise exc_info[0], exc_info[1], exc_info[2]
52 finally:
53 exc_info = None # avoid dangling circular ref
54 elif headers_set:
55 raise AssertionError("Headers already set!")
56
57 headers_set[:] = [status,response_headers]
58 return write
59
60 result = application(environ, start_response)
61 try:
62 for data in result:
63 if data: # don't send headers until body appears
64 write(data)
65 if not headers_sent:
66 write('') # send headers now if body was empty
67 finally:
68 if hasattr(result,'close'):
69 result.close()