Mercurial > hg
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() |