Mercurial > hg
view mercurial/hgweb/wsgicgi.py @ 30763:a520aefb96f1
httppeer: advertise and support application/mercurial-0.2
Now that servers expose a capability indicating they support
application/mercurial-0.2 and compression, clients can key off
this to say they support responses that are compressed with
various compression formats.
After this commit, the HTTP wire protocol client now sends an
"X-HgProto-<N>" request header indicating its support for
"application/mercurial-0.2" media type and various compression
formats.
This commit also implements support for handling
"application/mercurial-0.2" responses. It simply reads the header
compression engine identifier then routes the remainder of the
response to the appropriate decompressor.
There were some test changes, but only to logging. That points to
an obvious gap in our test coverage. This will be addressed in a
subsequent commit once server support is in place (it is hard to
test without server support).
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 24 Dec 2016 15:22:18 -0700 |
parents | f1c9fafcbf46 |
children | a57c938e7ac8 |
line wrap: on
line source
# hgweb/wsgicgi.py - CGI->WSGI translator # # Copyright 2006 Eric Hopper <hopper@omnifarious.org> # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. # # This was originally copied from the public domain code at # http://www.python.org/dev/peps/pep-0333/#the-server-gateway-side from __future__ import absolute_import from .. import ( encoding, util, ) from . import ( common, ) def launch(application): util.setbinary(util.stdin) util.setbinary(util.stdout) environ = dict(encoding.environ.iteritems()) environ.setdefault('PATH_INFO', '') if environ.get('SERVER_SOFTWARE', '').startswith('Microsoft-IIS'): # IIS includes script_name in PATH_INFO scriptname = environ['SCRIPT_NAME'] if environ['PATH_INFO'].startswith(scriptname): environ['PATH_INFO'] = environ['PATH_INFO'][len(scriptname):] stdin = util.stdin if environ.get('HTTP_EXPECT', '').lower() == '100-continue': stdin = common.continuereader(stdin, util.stdout.write) environ['wsgi.input'] = stdin environ['wsgi.errors'] = util.stderr environ['wsgi.version'] = (1, 0) environ['wsgi.multithread'] = False environ['wsgi.multiprocess'] = True environ['wsgi.run_once'] = True if environ.get('HTTPS', 'off').lower() in ('on', '1', 'yes'): environ['wsgi.url_scheme'] = 'https' else: environ['wsgi.url_scheme'] = 'http' headers_set = [] headers_sent = [] out = util.stdout def write(data): if not headers_set: raise AssertionError("write() before start_response()") elif not headers_sent: # Before the first output, send the stored headers status, response_headers = headers_sent[:] = headers_set out.write('Status: %s\r\n' % status) for header in response_headers: out.write('%s: %s\r\n' % header) out.write('\r\n') out.write(data) out.flush() def start_response(status, response_headers, exc_info=None): if exc_info: try: if headers_sent: # Re-raise original exception if headers sent raise exc_info[0](exc_info[1], exc_info[2]) finally: exc_info = None # avoid dangling circular ref elif headers_set: raise AssertionError("Headers already set!") headers_set[:] = [status, response_headers] return write content = application(environ, start_response) try: for chunk in content: write(chunk) if not headers_sent: write('') # send headers now if body was empty finally: getattr(content, 'close', lambda : None)()