mercurial/hgweb/request.py
author Gregory Szorc <gregory.szorc@gmail.com>
Thu, 08 Mar 2018 15:37:05 -0800
changeset 36811 cfb9ef24968c
parent 36809 3c15b84ab66c
child 36814 f9078c6caeb6
permissions -rw-r--r--
hgweb: use parsed request to construct query parameters The way hgweb routes requests is kind of bonkers. If PATH_INFO is set, we take the URL path after the repository. Otherwise, we take the first part of the query string before "&" and the part before ";" in that. We then kinda/sorta treat this as a path and route based on that. This commit ports that code to use the parsed request object. This required a new attribute on the parsed request to indicate whether there is any PATH_INFO. The new code still feels a bit convoluted for my liking. But we'll need to rewrite more of the code before a better solution becomes apparant. This code feels strictly better since we're no longer doing low-level WSGI manipulation during routing. Differential Revision: https://phab.mercurial-scm.org/D2739
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2391
d351a3be3371 Fixing up comment headers for split up code.
Eric Hopper <hopper@omnifarious.org>
parents: 2355
diff changeset
     1
# hgweb/request.py - An http request from either CGI or the standalone server.
131
c9d51742471c moving hgweb to mercurial subdir
jake@edge2.net
parents:
diff changeset
     2
#
238
3b92f8fe47ae hgweb.py: kill #! line, clean up copyright notice
mpm@selenic.com
parents: 222
diff changeset
     3
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
2859
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2535
diff changeset
     4
# Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
131
c9d51742471c moving hgweb to mercurial subdir
jake@edge2.net
parents:
diff changeset
     5
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7742
diff changeset
     6
# 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: 10261
diff changeset
     7
# GNU General Public License version 2 or any later version.
131
c9d51742471c moving hgweb to mercurial subdir
jake@edge2.net
parents:
diff changeset
     8
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
     9
from __future__ import absolute_import
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    10
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    11
import cgi
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    12
import errno
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    13
import socket
36806
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    14
#import wsgiref.validate
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    15
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    16
from .common import (
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    17
    ErrorResponse,
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    18
    HTTP_NOT_MODIFIED,
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    19
    statusmessage,
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    20
)
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    21
36806
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    22
from ..thirdparty import (
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    23
    attr,
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    24
)
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    25
from .. import (
34514
528b21b853aa request: coerce content-type to native str
Augie Fackler <augie@google.com>
parents: 34513
diff changeset
    26
    pycompat,
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    27
    util,
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 26846
diff changeset
    28
)
138
c77a679e9cfa Revamped templated hgweb
mpm@selenic.com
parents: 137
diff changeset
    29
6774
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    30
shortcuts = {
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    31
    'cl': [('cmd', ['changelog']), ('rev', None)],
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    32
    'sl': [('cmd', ['shortlog']), ('rev', None)],
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    33
    'cs': [('cmd', ['changeset']), ('node', None)],
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    34
    'f': [('cmd', ['file']), ('filenode', None)],
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    35
    'fl': [('cmd', ['filelog']), ('filenode', None)],
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    36
    'fd': [('cmd', ['filediff']), ('node', None)],
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    37
    'fa': [('cmd', ['annotate']), ('filenode', None)],
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    38
    'mf': [('cmd', ['manifest']), ('manifest', None)],
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    39
    'ca': [('cmd', ['archive']), ('node', None)],
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    40
    'tags': [('cmd', ['tags'])],
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    41
    'tip': [('cmd', ['changeset']), ('node', ['tip'])],
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    42
    'static': [('cmd', ['static']), ('file', None)]
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    43
}
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    44
10261
5eae671c0b57 hgweb: request: strip() form values
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9694
diff changeset
    45
def normalize(form):
5eae671c0b57 hgweb: request: strip() form values
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9694
diff changeset
    46
    # first expand the shortcuts
34513
34fcb0f66837 request: use trivial iterator over dictionary keys
Augie Fackler <augie@google.com>
parents: 34512
diff changeset
    47
    for k in shortcuts:
6774
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    48
        if k in form:
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    49
            for name, value in shortcuts[k]:
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    50
                if value is None:
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    51
                    value = form[k]
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    52
                form[name] = value
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    53
            del form[k]
10261
5eae671c0b57 hgweb: request: strip() form values
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9694
diff changeset
    54
    # And strip the values
36713
2442927cdd96 hgweb: convert req.form to bytes for all keys and values
Augie Fackler <augie@google.com>
parents: 36258
diff changeset
    55
    bytesform = {}
10261
5eae671c0b57 hgweb: request: strip() form values
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9694
diff changeset
    56
    for k, v in form.iteritems():
36713
2442927cdd96 hgweb: convert req.form to bytes for all keys and values
Augie Fackler <augie@google.com>
parents: 36258
diff changeset
    57
        bytesform[pycompat.bytesurl(k)] = [
2442927cdd96 hgweb: convert req.form to bytes for all keys and values
Augie Fackler <augie@google.com>
parents: 36258
diff changeset
    58
            pycompat.bytesurl(i.strip()) for i in v]
2442927cdd96 hgweb: convert req.form to bytes for all keys and values
Augie Fackler <augie@google.com>
parents: 36258
diff changeset
    59
    return bytesform
6774
0dbb56e90a71 hgweb: move shortcut expansion to request instantiation
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6212
diff changeset
    60
36806
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    61
@attr.s(frozen=True)
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    62
class parsedrequest(object):
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    63
    """Represents a parsed WSGI request / static HTTP request parameters."""
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    64
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    65
    # Full URL for this request.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    66
    url = attr.ib()
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    67
    # URL without any path components. Just <proto>://<host><port>.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    68
    baseurl = attr.ib()
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    69
    # Advertised URL. Like ``url`` and ``baseurl`` but uses SERVER_NAME instead
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    70
    # of HTTP: Host header for hostname. This is likely what clients used.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    71
    advertisedurl = attr.ib()
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    72
    advertisedbaseurl = attr.ib()
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    73
    # WSGI application path.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    74
    apppath = attr.ib()
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    75
    # List of path parts to be used for dispatch.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    76
    dispatchparts = attr.ib()
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    77
    # URL path component (no query string) used for dispatch.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    78
    dispatchpath = attr.ib()
36811
cfb9ef24968c hgweb: use parsed request to construct query parameters
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36809
diff changeset
    79
    # Whether there is a path component to this request. This can be true
cfb9ef24968c hgweb: use parsed request to construct query parameters
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36809
diff changeset
    80
    # when ``dispatchpath`` is empty due to REPO_NAME muckery.
cfb9ef24968c hgweb: use parsed request to construct query parameters
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36809
diff changeset
    81
    havepathinfo = attr.ib()
36806
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    82
    # Raw query string (part after "?" in URL).
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    83
    querystring = attr.ib()
36809
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
    84
    # List of 2-tuples of query string arguments.
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
    85
    querystringlist = attr.ib()
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
    86
    # Dict of query string arguments. Values are lists with at least 1 item.
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
    87
    querystringdict = attr.ib()
36806
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    88
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    89
def parserequestfromenv(env):
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    90
    """Parse URL components from environment variables.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    91
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    92
    WSGI defines request attributes via environment variables. This function
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    93
    parses the environment variables into a data structure.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    94
    """
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    95
    # PEP-0333 defines the WSGI spec and is a useful reference for this code.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    96
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    97
    # We first validate that the incoming object conforms with the WSGI spec.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    98
    # We only want to be dealing with spec-conforming WSGI implementations.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
    99
    # TODO enable this once we fix internal violations.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   100
    #wsgiref.validate.check_environ(env)
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   101
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   102
    # PEP-0333 states that environment keys and values are native strings
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   103
    # (bytes on Python 2 and str on Python 3). The code points for the Unicode
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   104
    # strings on Python 3 must be between \00000-\000FF. We deal with bytes
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   105
    # in Mercurial, so mass convert string keys and values to bytes.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   106
    if pycompat.ispy3:
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   107
        env = {k.encode('latin-1'): v for k, v in env.iteritems()}
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   108
        env = {k: v.encode('latin-1') if isinstance(v, str) else v
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   109
               for k, v in env.iteritems()}
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   110
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   111
    # https://www.python.org/dev/peps/pep-0333/#environ-variables defines
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   112
    # the environment variables.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   113
    # https://www.python.org/dev/peps/pep-0333/#url-reconstruction defines
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   114
    # how URLs are reconstructed.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   115
    fullurl = env['wsgi.url_scheme'] + '://'
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   116
    advertisedfullurl = fullurl
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   117
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   118
    def addport(s):
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   119
        if env['wsgi.url_scheme'] == 'https':
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   120
            if env['SERVER_PORT'] != '443':
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   121
                s += ':' + env['SERVER_PORT']
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   122
        else:
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   123
            if env['SERVER_PORT'] != '80':
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   124
                s += ':' + env['SERVER_PORT']
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   125
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   126
        return s
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   127
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   128
    if env.get('HTTP_HOST'):
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   129
        fullurl += env['HTTP_HOST']
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   130
    else:
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   131
        fullurl += env['SERVER_NAME']
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   132
        fullurl = addport(fullurl)
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   133
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   134
    advertisedfullurl += env['SERVER_NAME']
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   135
    advertisedfullurl = addport(advertisedfullurl)
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   136
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   137
    baseurl = fullurl
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   138
    advertisedbaseurl = advertisedfullurl
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   139
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   140
    fullurl += util.urlreq.quote(env.get('SCRIPT_NAME', ''))
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   141
    advertisedfullurl += util.urlreq.quote(env.get('SCRIPT_NAME', ''))
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   142
    fullurl += util.urlreq.quote(env.get('PATH_INFO', ''))
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   143
    advertisedfullurl += util.urlreq.quote(env.get('PATH_INFO', ''))
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   144
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   145
    if env.get('QUERY_STRING'):
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   146
        fullurl += '?' + env['QUERY_STRING']
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   147
        advertisedfullurl += '?' + env['QUERY_STRING']
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   148
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   149
    # When dispatching requests, we look at the URL components (PATH_INFO
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   150
    # and QUERY_STRING) after the application root (SCRIPT_NAME). But hgwebdir
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   151
    # has the concept of "virtual" repositories. This is defined via REPO_NAME.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   152
    # If REPO_NAME is defined, we append it to SCRIPT_NAME to form a new app
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   153
    # root. We also exclude its path components from PATH_INFO when resolving
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   154
    # the dispatch path.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   155
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   156
    apppath = env['SCRIPT_NAME']
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   157
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   158
    if env.get('REPO_NAME'):
36808
0031e972ded2 hgweb: use the parsed application path directly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36806
diff changeset
   159
        if not apppath.endswith('/'):
0031e972ded2 hgweb: use the parsed application path directly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36806
diff changeset
   160
            apppath += '/'
0031e972ded2 hgweb: use the parsed application path directly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36806
diff changeset
   161
0031e972ded2 hgweb: use the parsed application path directly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36806
diff changeset
   162
        apppath += env.get('REPO_NAME')
36806
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   163
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   164
    if 'PATH_INFO' in env:
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   165
        dispatchparts = env['PATH_INFO'].strip('/').split('/')
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   166
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   167
        # Strip out repo parts.
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   168
        repoparts = env.get('REPO_NAME', '').split('/')
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   169
        if dispatchparts[:len(repoparts)] == repoparts:
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   170
            dispatchparts = dispatchparts[len(repoparts):]
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   171
    else:
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   172
        dispatchparts = []
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   173
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   174
    dispatchpath = '/'.join(dispatchparts)
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   175
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   176
    querystring = env.get('QUERY_STRING', '')
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   177
36809
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   178
    # We store as a list so we have ordering information. We also store as
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   179
    # a dict to facilitate fast lookup.
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   180
    querystringlist = util.urlreq.parseqsl(querystring, keep_blank_values=True)
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   181
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   182
    querystringdict = {}
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   183
    for k, v in querystringlist:
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   184
        if k in querystringdict:
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   185
            querystringdict[k].append(v)
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   186
        else:
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   187
            querystringdict[k] = [v]
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   188
36806
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   189
    return parsedrequest(url=fullurl, baseurl=baseurl,
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   190
                         advertisedurl=advertisedfullurl,
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   191
                         advertisedbaseurl=advertisedbaseurl,
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   192
                         apppath=apppath,
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   193
                         dispatchparts=dispatchparts, dispatchpath=dispatchpath,
36811
cfb9ef24968c hgweb: use parsed request to construct query parameters
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36809
diff changeset
   194
                         havepathinfo='PATH_INFO' in env,
36809
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   195
                         querystring=querystring,
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   196
                         querystringlist=querystringlist,
3c15b84ab66c hgweb: teach WSGI parser about query strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36808
diff changeset
   197
                         querystringdict=querystringdict)
36806
69b2d0900cd7 hgweb: parse WSGI request into a data structure
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36713
diff changeset
   198
5566
d74fc8dec2b4 Less indirection in the WSGI web interface. This simplifies some code, and makes it more compliant with WSGI.
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5563
diff changeset
   199
class wsgirequest(object):
26132
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
   200
    """Higher-level API for a WSGI request.
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
   201
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
   202
    WSGI applications are invoked with 2 arguments. They are used to
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
   203
    instantiate instances of this class, which provides higher-level APIs
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
   204
    for obtaining request parameters, writing HTTP output, etc.
9df8c729e2e7 hgweb: add some documentation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
   205
    """
5566
d74fc8dec2b4 Less indirection in the WSGI web interface. This simplifies some code, and makes it more compliant with WSGI.
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5563
diff changeset
   206
    def __init__(self, wsgienv, start_response):
34512
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 27046
diff changeset
   207
        version = wsgienv[r'wsgi.version']
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2859
diff changeset
   208
        if (version < (1, 0)) or (version >= (2, 0)):
4633
ff7253a0d1da Cleanup of whitespace, indentation and line continuation.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4250
diff changeset
   209
            raise RuntimeError("Unknown and unsupported WSGI version %d.%d"
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents: 2466
diff changeset
   210
                               % version)
34512
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 27046
diff changeset
   211
        self.inp = wsgienv[r'wsgi.input']
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 27046
diff changeset
   212
        self.err = wsgienv[r'wsgi.errors']
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 27046
diff changeset
   213
        self.threaded = wsgienv[r'wsgi.multithread']
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 27046
diff changeset
   214
        self.multiprocess = wsgienv[r'wsgi.multiprocess']
482d6f6dba91 hgweb: when constructing or adding to a wsgi environ dict, use native strs
Augie Fackler <augie@google.com>
parents: 27046
diff changeset
   215
        self.run_once = wsgienv[r'wsgi.run_once']
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents: 2466
diff changeset
   216
        self.env = wsgienv
10261
5eae671c0b57 hgweb: request: strip() form values
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9694
diff changeset
   217
        self.form = normalize(cgi.parse(self.inp,
5eae671c0b57 hgweb: request: strip() form values
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9694
diff changeset
   218
                                        self.env,
5eae671c0b57 hgweb: request: strip() form values
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9694
diff changeset
   219
                                        keep_blank_values=1))
5888
956afc025c0f hgweb: separate out start_response() calling
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5887
diff changeset
   220
        self._start_response = start_response
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
   221
        self.server_write = None
2506
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents: 2466
diff changeset
   222
        self.headers = []
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents: 2466
diff changeset
   223
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents: 2466
diff changeset
   224
    def __iter__(self):
d0db3462d568 This patch make several WSGI related alterations.
Eric Hopper <hopper@omnifarious.org>
parents: 2466
diff changeset
   225
        return iter([])
131
c9d51742471c moving hgweb to mercurial subdir
jake@edge2.net
parents:
diff changeset
   226
2464
09b1c9ef317c push over http: server support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2434
diff changeset
   227
    def read(self, count=-1):
09b1c9ef317c push over http: server support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2434
diff changeset
   228
        return self.inp.read(count)
09b1c9ef317c push over http: server support.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2434
diff changeset
   229
7180
a42d27bc809d hgweb: be sure to drain request data even in early error conditions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6774
diff changeset
   230
    def drain(self):
a42d27bc809d hgweb: be sure to drain request data even in early error conditions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6774
diff changeset
   231
        '''need to read all data from request, httplib is half-duplex'''
13600
bcc59cb3714d hgweb: pmezard thinks one default is enough
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 13598
diff changeset
   232
        length = int(self.env.get('CONTENT_LENGTH') or 0)
7180
a42d27bc809d hgweb: be sure to drain request data even in early error conditions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6774
diff changeset
   233
        for s in util.filechunkiter(self.inp, limit=length):
a42d27bc809d hgweb: be sure to drain request data even in early error conditions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6774
diff changeset
   234
            pass
a42d27bc809d hgweb: be sure to drain request data even in early error conditions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6774
diff changeset
   235
18352
e33b9b92a200 hgweb: pass the actual response body to request.response, not just the length
Mads Kiilerich <mads@kiilerich.com>
parents: 18351
diff changeset
   236
    def respond(self, status, type, filename=None, body=None):
34514
528b21b853aa request: coerce content-type to native str
Augie Fackler <augie@google.com>
parents: 34513
diff changeset
   237
        if not isinstance(type, str):
528b21b853aa request: coerce content-type to native str
Augie Fackler <augie@google.com>
parents: 34513
diff changeset
   238
            type = pycompat.sysstr(type)
5888
956afc025c0f hgweb: separate out start_response() calling
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5887
diff changeset
   239
        if self._start_response is not None:
34722
95be8928d6b2 hgweb: fill in content-type and content-length as native strings
Augie Fackler <augie@google.com>
parents: 34514
diff changeset
   240
            self.headers.append((r'Content-Type', type))
18348
764a758780b6 hgweb: simplify wsgirequest header handling
Mads Kiilerich <mads@kiilerich.com>
parents: 18347
diff changeset
   241
            if filename:
26846
7c1b4840c2cd hgweb: replace some str.split() calls by str.partition() or str.rpartition()
Anton Shestakov <av6@dwimlabs.net>
parents: 26200
diff changeset
   242
                filename = (filename.rpartition('/')[-1]
18348
764a758780b6 hgweb: simplify wsgirequest header handling
Mads Kiilerich <mads@kiilerich.com>
parents: 18347
diff changeset
   243
                            .replace('\\', '\\\\').replace('"', '\\"'))
764a758780b6 hgweb: simplify wsgirequest header handling
Mads Kiilerich <mads@kiilerich.com>
parents: 18347
diff changeset
   244
                self.headers.append(('Content-Disposition',
764a758780b6 hgweb: simplify wsgirequest header handling
Mads Kiilerich <mads@kiilerich.com>
parents: 18347
diff changeset
   245
                                     'inline; filename="%s"' % filename))
18352
e33b9b92a200 hgweb: pass the actual response body to request.response, not just the length
Mads Kiilerich <mads@kiilerich.com>
parents: 18351
diff changeset
   246
            if body is not None:
34722
95be8928d6b2 hgweb: fill in content-type and content-length as native strings
Augie Fackler <augie@google.com>
parents: 34514
diff changeset
   247
                self.headers.append((r'Content-Length', str(len(body))))
5888
956afc025c0f hgweb: separate out start_response() calling
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5887
diff changeset
   248
5926
15ef6b9c1f2f hgweb: be sure to send a valid content-type for raw files
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5922
diff changeset
   249
            for k, v in self.headers:
15ef6b9c1f2f hgweb: be sure to send a valid content-type for raw files
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5922
diff changeset
   250
                if not isinstance(v, str):
18348
764a758780b6 hgweb: simplify wsgirequest header handling
Mads Kiilerich <mads@kiilerich.com>
parents: 18347
diff changeset
   251
                    raise TypeError('header value must be string: %r' % (v,))
5926
15ef6b9c1f2f hgweb: be sure to send a valid content-type for raw files
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5922
diff changeset
   252
5888
956afc025c0f hgweb: separate out start_response() calling
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5887
diff changeset
   253
            if isinstance(status, ErrorResponse):
18348
764a758780b6 hgweb: simplify wsgirequest header handling
Mads Kiilerich <mads@kiilerich.com>
parents: 18347
diff changeset
   254
                self.headers.extend(status.headers)
12739
8dcd3203a261 hgweb: don't send a body or illegal headers during 304 response
Augie Fackler <durin42@gmail.com>
parents: 10263
diff changeset
   255
                if status.code == HTTP_NOT_MODIFIED:
8dcd3203a261 hgweb: don't send a body or illegal headers during 304 response
Augie Fackler <durin42@gmail.com>
parents: 10263
diff changeset
   256
                    # RFC 2616 Section 10.3.5: 304 Not Modified has cases where
8dcd3203a261 hgweb: don't send a body or illegal headers during 304 response
Augie Fackler <durin42@gmail.com>
parents: 10263
diff changeset
   257
                    # it MUST NOT include any headers other than these and no
8dcd3203a261 hgweb: don't send a body or illegal headers during 304 response
Augie Fackler <durin42@gmail.com>
parents: 10263
diff changeset
   258
                    # body
8dcd3203a261 hgweb: don't send a body or illegal headers during 304 response
Augie Fackler <durin42@gmail.com>
parents: 10263
diff changeset
   259
                    self.headers = [(k, v) for (k, v) in self.headers if
8dcd3203a261 hgweb: don't send a body or illegal headers during 304 response
Augie Fackler <durin42@gmail.com>
parents: 10263
diff changeset
   260
                                    k in ('Date', 'ETag', 'Expires',
8dcd3203a261 hgweb: don't send a body or illegal headers during 304 response
Augie Fackler <durin42@gmail.com>
parents: 10263
diff changeset
   261
                                          'Cache-Control', 'Vary')]
36255
a0a004b29a51 hgweb: correctly bytes-ify status, not string-ify
Augie Fackler <augie@google.com>
parents: 34722
diff changeset
   262
                status = statusmessage(status.code, pycompat.bytestr(status))
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
   263
            elif status == 200:
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
   264
                status = '200 Script output follows'
5888
956afc025c0f hgweb: separate out start_response() calling
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5887
diff changeset
   265
            elif isinstance(status, int):
956afc025c0f hgweb: separate out start_response() calling
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5887
diff changeset
   266
                status = statusmessage(status)
956afc025c0f hgweb: separate out start_response() calling
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5887
diff changeset
   267
36258
af0a19d8812b py3: get bytes-repr of network errors portably
Augie Fackler <augie@google.com>
parents: 36255
diff changeset
   268
            self.server_write = self._start_response(
af0a19d8812b py3: get bytes-repr of network errors portably
Augie Fackler <augie@google.com>
parents: 36255
diff changeset
   269
                pycompat.sysstr(status), self.headers)
5888
956afc025c0f hgweb: separate out start_response() calling
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5887
diff changeset
   270
            self._start_response = None
956afc025c0f hgweb: separate out start_response() calling
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5887
diff changeset
   271
            self.headers = []
18352
e33b9b92a200 hgweb: pass the actual response body to request.response, not just the length
Mads Kiilerich <mads@kiilerich.com>
parents: 18351
diff changeset
   272
        if body is not None:
e33b9b92a200 hgweb: pass the actual response body to request.response, not just the length
Mads Kiilerich <mads@kiilerich.com>
parents: 18351
diff changeset
   273
            self.write(body)
e33b9b92a200 hgweb: pass the actual response body to request.response, not just the length
Mads Kiilerich <mads@kiilerich.com>
parents: 18351
diff changeset
   274
            self.server_write = None
5888
956afc025c0f hgweb: separate out start_response() calling
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5887
diff changeset
   275
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
   276
    def write(self, thing):
18351
3fbdbeab38cc hgweb: don't pass empty response chunks on
Mads Kiilerich <mads@kiilerich.com>
parents: 18350
diff changeset
   277
        if thing:
3fbdbeab38cc hgweb: don't pass empty response chunks on
Mads Kiilerich <mads@kiilerich.com>
parents: 18350
diff changeset
   278
            try:
3fbdbeab38cc hgweb: don't pass empty response chunks on
Mads Kiilerich <mads@kiilerich.com>
parents: 18350
diff changeset
   279
                self.server_write(thing)
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 18352
diff changeset
   280
            except socket.error as inst:
18351
3fbdbeab38cc hgweb: don't pass empty response chunks on
Mads Kiilerich <mads@kiilerich.com>
parents: 18350
diff changeset
   281
                if inst[0] != errno.ECONNRESET:
3fbdbeab38cc hgweb: don't pass empty response chunks on
Mads Kiilerich <mads@kiilerich.com>
parents: 18350
diff changeset
   282
                    raise
1159
b6f5a947e62e Change use of global sys.stdout, sys.stdin os.environ to a hgrequest object.
Vincent Wagelaar <vincent@ricardis.tudelft.nl>
parents: 1143
diff changeset
   283
4246
cc81c512a531 avoid _wsgioutputfile <-> _wsgirequest circular reference
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   284
    def writelines(self, lines):
cc81c512a531 avoid _wsgioutputfile <-> _wsgirequest circular reference
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   285
        for line in lines:
cc81c512a531 avoid _wsgioutputfile <-> _wsgirequest circular reference
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   286
            self.write(line)
cc81c512a531 avoid _wsgioutputfile <-> _wsgirequest circular reference
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   287
cc81c512a531 avoid _wsgioutputfile <-> _wsgirequest circular reference
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   288
    def flush(self):
cc81c512a531 avoid _wsgioutputfile <-> _wsgirequest circular reference
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   289
        return None
cc81c512a531 avoid _wsgioutputfile <-> _wsgirequest circular reference
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   290
cc81c512a531 avoid _wsgioutputfile <-> _wsgirequest circular reference
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   291
    def close(self):
cc81c512a531 avoid _wsgioutputfile <-> _wsgirequest circular reference
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   292
        return None
cc81c512a531 avoid _wsgioutputfile <-> _wsgirequest circular reference
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   293
5566
d74fc8dec2b4 Less indirection in the WSGI web interface. This simplifies some code, and makes it more compliant with WSGI.
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5563
diff changeset
   294
def wsgiapplication(app_maker):
5887
41a3fce17625 hgweb: return iterable, add deprecation note
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5886
diff changeset
   295
    '''For compatibility with old CGI scripts. A plain hgweb() or hgwebdir()
41a3fce17625 hgweb: return iterable, add deprecation note
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5886
diff changeset
   296
    can and should now be used as a WSGI application.'''
5760
0145f9afb0e7 Removed tabs and trailing whitespace in python files
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5566
diff changeset
   297
    application = app_maker()
0145f9afb0e7 Removed tabs and trailing whitespace in python files
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5566
diff changeset
   298
    def run_wsgi(env, respond):
5887
41a3fce17625 hgweb: return iterable, add deprecation note
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5886
diff changeset
   299
        return application(env, respond)
5760
0145f9afb0e7 Removed tabs and trailing whitespace in python files
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5566
diff changeset
   300
    return run_wsgi