wsgicgi.py
94 lines
| 3.0 KiB
| text/x-python
|
PythonLexer
Eric Hopper
|
r2506 | # hgweb/wsgicgi.py - CGI->WSGI translator | ||
# | ||||
# Copyright 2006 Eric Hopper <hopper@omnifarious.org> | ||||
# | ||||
Martin Geisler
|
r8225 | # This software may be used and distributed according to the terms of the | ||
Matt Mackall
|
r10263 | # GNU General Public License version 2 or any later version. | ||
Eric Hopper
|
r2506 | # | ||
# This was originally copied from the public domain code at | ||||
# http://www.python.org/dev/peps/pep-0333/#the-server-gateway-side | ||||
Matt Harbison
|
r52756 | from __future__ import annotations | ||
Yuya Nishihara
|
r27046 | |||
Manuel Jacob
|
r51830 | from .. import encoding, pycompat | ||
Yuya Nishihara
|
r27046 | |||
Augie Fackler
|
r43346 | from ..utils import procutil | ||
Yuya Nishihara
|
r37137 | |||
Augie Fackler
|
r43346 | from . import common | ||
Eric Hopper
|
r2506 | |||
def launch(application): | ||||
Yuya Nishihara
|
r37138 | procutil.setbinary(procutil.stdin) | ||
procutil.setbinary(procutil.stdout) | ||||
Eric Hopper
|
r2506 | |||
Manuel Jacob
|
r51830 | environ = { | ||
k.decode('iso8859-1'): v.decode('iso8859-1') | ||||
for k, v in encoding.environ.items() | ||||
} # re-exports | ||||
Matt Harbison
|
r47529 | environ.setdefault('PATH_INFO', '') | ||
Augie Fackler
|
r43906 | if environ.get('SERVER_SOFTWARE', '').startswith('Microsoft-IIS'): | ||
Mads Kiilerich
|
r17424 | # IIS includes script_name in PATH_INFO | ||
Augie Fackler
|
r43906 | scriptname = environ['SCRIPT_NAME'] | ||
if environ['PATH_INFO'].startswith(scriptname): | ||||
environ['PATH_INFO'] = environ['PATH_INFO'][len(scriptname) :] | ||||
Dirkjan Ochtman
|
r7406 | |||
Yuya Nishihara
|
r37137 | stdin = procutil.stdin | ||
Augie Fackler
|
r43906 | if environ.get('HTTP_EXPECT', '').lower() == '100-continue': | ||
Yuya Nishihara
|
r37137 | stdin = common.continuereader(stdin, procutil.stdout.write) | ||
Augie Fackler
|
r13570 | |||
Augie Fackler
|
r43906 | environ['wsgi.input'] = stdin | ||
environ['wsgi.errors'] = procutil.stderr | ||||
environ['wsgi.version'] = (1, 0) | ||||
environ['wsgi.multithread'] = False | ||||
environ['wsgi.multiprocess'] = True | ||||
environ['wsgi.run_once'] = True | ||||
Eric Hopper
|
r2506 | |||
Augie Fackler
|
r43906 | if environ.get('HTTPS', 'off').lower() in ('on', '1', 'yes'): | ||
environ['wsgi.url_scheme'] = 'https' | ||||
Eric Hopper
|
r2506 | else: | ||
Augie Fackler
|
r43906 | environ['wsgi.url_scheme'] = 'http' | ||
Eric Hopper
|
r2506 | |||
headers_set = [] | ||||
headers_sent = [] | ||||
Yuya Nishihara
|
r37137 | out = procutil.stdout | ||
Eric Hopper
|
r2506 | |||
def write(data): | ||||
if not headers_set: | ||||
Augie Fackler
|
r43347 | raise AssertionError(b"write() before start_response()") | ||
Eric Hopper
|
r2506 | |||
elif not headers_sent: | ||||
Thomas Arendsen Hein
|
r3673 | # Before the first output, send the stored headers | ||
status, response_headers = headers_sent[:] = headers_set | ||||
Augie Fackler
|
r43347 | out.write(b'Status: %s\r\n' % pycompat.bytesurl(status)) | ||
Augie Fackler
|
r37765 | for hk, hv in response_headers: | ||
Augie Fackler
|
r43346 | out.write( | ||
Augie Fackler
|
r43347 | b'%s: %s\r\n' | ||
Augie Fackler
|
r43346 | % (pycompat.bytesurl(hk), pycompat.bytesurl(hv)) | ||
) | ||||
Augie Fackler
|
r43347 | out.write(b'\r\n') | ||
Eric Hopper
|
r2506 | |||
Alexis S. L. Carvalho
|
r2558 | out.write(data) | ||
out.flush() | ||||
Eric Hopper
|
r2506 | |||
Thomas Arendsen Hein
|
r3673 | def start_response(status, response_headers, exc_info=None): | ||
Eric Hopper
|
r2506 | if exc_info: | ||
try: | ||||
if headers_sent: | ||||
# Re-raise original exception if headers sent | ||||
Peter Ruibal
|
r7008 | raise exc_info[0](exc_info[1], exc_info[2]) | ||
Eric Hopper
|
r2506 | finally: | ||
Matt Harbison
|
r44445 | del exc_info # avoid dangling circular ref | ||
Eric Hopper
|
r2506 | elif headers_set: | ||
Augie Fackler
|
r43347 | raise AssertionError(b"Headers already set!") | ||
Eric Hopper
|
r2506 | |||
Thomas Arendsen Hein
|
r3673 | headers_set[:] = [status, response_headers] | ||
Eric Hopper
|
r2506 | return write | ||
Dirkjan Ochtman
|
r6922 | content = application(environ, start_response) | ||
Konstantin Zemlyak
|
r10753 | try: | ||
for chunk in content: | ||||
write(chunk) | ||||
Mads Kiilerich
|
r18552 | if not headers_sent: | ||
Augie Fackler
|
r43347 | write(b'') # send headers now if body was empty | ||
Konstantin Zemlyak
|
r10753 | finally: | ||
Alex Gaynor
|
r34487 | getattr(content, 'close', lambda: None)() | ||