paulb@307 | 1 | #!/usr/local/bin/python |
paulb@307 | 2 | |
paulb@307 | 3 | """ |
paulb@307 | 4 | WSGI CGI handler code originating from PEP 333, transcribed by Titus Brown. |
paulb@307 | 5 | Previously a standalone CGI program, this is now a module imported by the actual |
paulb@307 | 6 | CGI programs. |
paulb@307 | 7 | """ |
paulb@307 | 8 | |
paulb@307 | 9 | import os, sys |
paulb@307 | 10 | |
paulb@307 | 11 | def run_with_cgi(application): |
paulb@307 | 12 | |
paulb@307 | 13 | environ = dict(os.environ.items()) |
paulb@307 | 14 | environ['wsgi.input'] = sys.stdin |
paulb@307 | 15 | environ['wsgi.errors'] = sys.stderr |
paulb@307 | 16 | environ['wsgi.version'] = (1,0) |
paulb@307 | 17 | environ['wsgi.multithread'] = False |
paulb@307 | 18 | environ['wsgi.multiprocess'] = True |
paulb@307 | 19 | environ['wsgi.run_once'] = True |
paulb@307 | 20 | |
paulb@307 | 21 | if environ.get('HTTPS','off') in ('on','1'): |
paulb@307 | 22 | environ['wsgi.url_scheme'] = 'https' |
paulb@307 | 23 | else: |
paulb@307 | 24 | environ['wsgi.url_scheme'] = 'http' |
paulb@307 | 25 | |
paulb@307 | 26 | headers_set = [] |
paulb@307 | 27 | headers_sent = [] |
paulb@307 | 28 | |
paulb@307 | 29 | def write(data): |
paulb@307 | 30 | if not headers_set: |
paulb@307 | 31 | raise AssertionError("write() before start_response()") |
paulb@307 | 32 | |
paulb@307 | 33 | elif not headers_sent: |
paulb@307 | 34 | # Before the first output, send the stored headers |
paulb@307 | 35 | status, response_headers = headers_sent[:] = headers_set |
paulb@307 | 36 | sys.stdout.write('Status: %s\r\n' % status) |
paulb@307 | 37 | for header in response_headers: |
paulb@307 | 38 | sys.stdout.write('%s: %s\r\n' % header) |
paulb@307 | 39 | sys.stdout.write('\r\n') |
paulb@307 | 40 | |
paulb@307 | 41 | sys.stdout.write(data) |
paulb@307 | 42 | sys.stdout.flush() |
paulb@307 | 43 | |
paulb@307 | 44 | def start_response(status,response_headers,exc_info=None): |
paulb@307 | 45 | if exc_info: |
paulb@307 | 46 | try: |
paulb@307 | 47 | if headers_sent: |
paulb@307 | 48 | # Re-raise original exception if headers sent |
paulb@307 | 49 | raise exc_info[0], exc_info[1], exc_info[2] |
paulb@307 | 50 | finally: |
paulb@307 | 51 | exc_info = None # avoid dangling circular ref |
paulb@307 | 52 | elif headers_set: |
paulb@307 | 53 | raise AssertionError("Headers already set!") |
paulb@307 | 54 | |
paulb@307 | 55 | headers_set[:] = [status,response_headers] |
paulb@307 | 56 | return write |
paulb@307 | 57 | |
paulb@307 | 58 | result = application(environ, start_response) |
paulb@307 | 59 | try: |
paulb@307 | 60 | for data in result: |
paulb@307 | 61 | if data: # don't send headers until body appears |
paulb@307 | 62 | write(data) |
paulb@307 | 63 | if not headers_sent: |
paulb@307 | 64 | write('') # send headers now if body was empty |
paulb@307 | 65 | finally: |
paulb@307 | 66 | if hasattr(result,'close'): |
paulb@307 | 67 | result.close() |
paulb@307 | 68 | |
paulb@307 | 69 | # vim: tabstop=4 expandtab shiftwidth=4 |