mercurial/hgweb/wsgicgi.py
author Gregory Szorc <gregory.szorc@gmail.com>
Mon, 08 Oct 2018 17:10:59 -0700
changeset 40132 e67522413ca8
parent 37747 2d5b5bcc3b9f
child 43076 2372284d9457
permissions -rw-r--r--
wireprotov2: define and use stream encoders Now that we have basic support for defining stream encoding, it is time to start doing something with it. We define various classes implementing stream encoders/decoders for the defined encoding profiles. This is relatively straightforward. We teach the inputstream and outputstream classes how to encode, decode, and flush data. We then teach the clientreactor how to filter received data through the inputstream decoder. One of the features of the framing format is that streams can span requests. This is a differentiating feature from say HTTP/2, which associates streams with requests. By allowing streams to span requests, we can reuse compression context data across requests/responses. But in order to do this, we need a mechanism to "flush" the encoder at logical boundaries so that receivers receive all data where it is expected. And a "flush" event is distinct from a "finish" event from the perspective of certain compressors because a "flush" will retain compression context state whereas a "finish" operation will not. This is why encoders have both a flush() and a finish() and each uses specific flushing semantics on the underlying compressor. The added tests verify various behavior of decoders via clientreactor. These tests do test some compression behavior via use of outputstream. But for all intents and purposes, server reactor support for encoding is not yet implemented. Differential Revision: https://phab.mercurial-scm.org/D4921
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
     1
# hgweb/wsgicgi.py - CGI->WSGI translator
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
     2
#
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
     3
# Copyright 2006 Eric Hopper <hopper@omnifarious.org>
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7622
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10201
diff changeset
     6
# GNU General Public License version 2 or any later version.
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
     7
#
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
     8
# This was originally copied from the public domain code at
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
     9
# http://www.python.org/dev/peps/pep-0333/#the-server-gateway-side
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    10
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 18552
diff changeset
    11
from __future__ import absolute_import
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 18552
diff changeset
    12
37747
2d5b5bcc3b9f wsgicgi: un-do some prior porting work that is now wrong
Augie Fackler <augie@google.com>
parents: 37120
diff changeset
    13
import os
2d5b5bcc3b9f wsgicgi: un-do some prior porting work that is now wrong
Augie Fackler <augie@google.com>
parents: 37120
diff changeset
    14
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 18552
diff changeset
    15
from .. import (
37747
2d5b5bcc3b9f wsgicgi: un-do some prior porting work that is now wrong
Augie Fackler <augie@google.com>
parents: 37120
diff changeset
    16
    pycompat,
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 18552
diff changeset
    17
)
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 18552
diff changeset
    18
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34512
diff changeset
    19
from ..utils import (
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34512
diff changeset
    20
    procutil,
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34512
diff changeset
    21
)
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34512
diff changeset
    22
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 18552
diff changeset
    23
from . import (
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 18552
diff changeset
    24
    common,
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 18552
diff changeset
    25
)
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    26
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    27
def launch(application):
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37119
diff changeset
    28
    procutil.setbinary(procutil.stdin)
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37119
diff changeset
    29
    procutil.setbinary(procutil.stdout)
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    30
37747
2d5b5bcc3b9f wsgicgi: un-do some prior porting work that is now wrong
Augie Fackler <augie@google.com>
parents: 37120
diff changeset
    31
    environ = dict(os.environ.iteritems()) # re-exports
34512
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    32
    environ.setdefault(r'PATH_INFO', '')
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    33
    if environ.get(r'SERVER_SOFTWARE', r'').startswith(r'Microsoft-IIS'):
17424
e7cfe3587ea4 fix trivial spelling errors
Mads Kiilerich <mads@kiilerich.com>
parents: 14956
diff changeset
    34
        # IIS includes script_name in PATH_INFO
34512
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    35
        scriptname = environ[r'SCRIPT_NAME']
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    36
        if environ[r'PATH_INFO'].startswith(scriptname):
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    37
            environ[r'PATH_INFO'] = environ[r'PATH_INFO'][len(scriptname):]
7406
ee8af8a4d905 hgweb: support broken IIS 5 behavior with .cgi in PATH_INFO
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7008
diff changeset
    38
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34512
diff changeset
    39
    stdin = procutil.stdin
34512
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    40
    if environ.get(r'HTTP_EXPECT', r'').lower() == r'100-continue':
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34512
diff changeset
    41
        stdin = common.continuereader(stdin, procutil.stdout.write)
13570
617a87cb7eb2 hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents: 10753
diff changeset
    42
34512
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    43
    environ[r'wsgi.input'] = stdin
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34512
diff changeset
    44
    environ[r'wsgi.errors'] = procutil.stderr
34512
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    45
    environ[r'wsgi.version'] = (1, 0)
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    46
    environ[r'wsgi.multithread'] = False
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    47
    environ[r'wsgi.multiprocess'] = True
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    48
    environ[r'wsgi.run_once'] = True
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    49
34512
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    50
    if environ.get(r'HTTPS', r'off').lower() in (r'on', r'1', r'yes'):
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    51
        environ[r'wsgi.url_scheme'] = r'https'
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    52
    else:
34512
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 34486
diff changeset
    53
        environ[r'wsgi.url_scheme'] = r'http'
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    54
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    55
    headers_set = []
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    56
    headers_sent = []
37119
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 34512
diff changeset
    57
    out = procutil.stdout
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    58
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    59
    def write(data):
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    60
        if not headers_set:
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2558
diff changeset
    61
            raise AssertionError("write() before start_response()")
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    62
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    63
        elif not headers_sent:
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2558
diff changeset
    64
            # Before the first output, send the stored headers
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2558
diff changeset
    65
            status, response_headers = headers_sent[:] = headers_set
37747
2d5b5bcc3b9f wsgicgi: un-do some prior porting work that is now wrong
Augie Fackler <augie@google.com>
parents: 37120
diff changeset
    66
            out.write('Status: %s\r\n' % pycompat.bytesurl(status))
2d5b5bcc3b9f wsgicgi: un-do some prior porting work that is now wrong
Augie Fackler <augie@google.com>
parents: 37120
diff changeset
    67
            for hk, hv in response_headers:
2d5b5bcc3b9f wsgicgi: un-do some prior porting work that is now wrong
Augie Fackler <augie@google.com>
parents: 37120
diff changeset
    68
                out.write('%s: %s\r\n' % (pycompat.bytesurl(hk),
2d5b5bcc3b9f wsgicgi: un-do some prior porting work that is now wrong
Augie Fackler <augie@google.com>
parents: 37120
diff changeset
    69
                                          pycompat.bytesurl(hv)))
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2558
diff changeset
    70
            out.write('\r\n')
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    71
2558
1120302009d7 hgweb: fix unbundle.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2506
diff changeset
    72
        out.write(data)
1120302009d7 hgweb: fix unbundle.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2506
diff changeset
    73
        out.flush()
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    74
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2558
diff changeset
    75
    def start_response(status, response_headers, exc_info=None):
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    76
        if exc_info:
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    77
            try:
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    78
                if headers_sent:
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    79
                    # Re-raise original exception if headers sent
7008
8fee8ff13d37 use Exception(args)-style raising consistently (py3k compatibility)
Peter Ruibal <peter.ruibal@intel.com>
parents: 6922
diff changeset
    80
                    raise exc_info[0](exc_info[1], exc_info[2])
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    81
            finally:
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    82
                exc_info = None     # avoid dangling circular ref
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    83
        elif headers_set:
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    84
            raise AssertionError("Headers already set!")
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    85
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2558
diff changeset
    86
        headers_set[:] = [status, response_headers]
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    87
        return write
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents:
diff changeset
    88
6922
1ec2d227a521 hgweb: fix WSGI iterators handling in CGI adapter (issue1254)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5580
diff changeset
    89
    content = application(environ, start_response)
10753
a1cb8ca051c0 wsgicgi: call close() on iterable to avoid resource leaks
Konstantin Zemlyak <zart@zartsoft.ru>
parents: 10339
diff changeset
    90
    try:
a1cb8ca051c0 wsgicgi: call close() on iterable to avoid resource leaks
Konstantin Zemlyak <zart@zartsoft.ru>
parents: 10339
diff changeset
    91
        for chunk in content:
a1cb8ca051c0 wsgicgi: call close() on iterable to avoid resource leaks
Konstantin Zemlyak <zart@zartsoft.ru>
parents: 10339
diff changeset
    92
            write(chunk)
18552
e8efcc8ff5c0 hgweb.cgi: fix internal WSGI emulation (issue3804)
Mads Kiilerich <madski@unity3d.com>
parents: 17424
diff changeset
    93
        if not headers_sent:
e8efcc8ff5c0 hgweb.cgi: fix internal WSGI emulation (issue3804)
Mads Kiilerich <madski@unity3d.com>
parents: 17424
diff changeset
    94
            write('')   # send headers now if body was empty
10753
a1cb8ca051c0 wsgicgi: call close() on iterable to avoid resource leaks
Konstantin Zemlyak <zart@zartsoft.ru>
parents: 10339
diff changeset
    95
    finally:
34486
a57c938e7ac8 style: never use a space before a colon or comma
Alex Gaynor <agaynor@mozilla.com>
parents: 30636
diff changeset
    96
        getattr(content, 'close', lambda: None)()