mercurial/hgweb/request.py
changeset 2506 d0db3462d568
parent 2466 e10665147d26
child 2507 7e01da2bc7f3
equal deleted inserted replaced
2505:01b856927970 2506:d0db3462d568
     8 
     8 
     9 from mercurial.demandload import demandload
     9 from mercurial.demandload import demandload
    10 demandload(globals(), "socket sys cgi os errno")
    10 demandload(globals(), "socket sys cgi os errno")
    11 from mercurial.i18n import gettext as _
    11 from mercurial.i18n import gettext as _
    12 
    12 
    13 class hgrequest(object):
    13 class wsgiapplication(object):
    14     def __init__(self, inp=None, out=None, env=None):
    14     def __init__(self, destmaker):
    15         self.inp = inp or sys.stdin
    15         self.destmaker = destmaker
    16         self.out = out or sys.stdout
    16 
    17         self.env = env or os.environ
    17     def __call__(self, wsgienv, start_response):
       
    18         return _wsgirequest(self.destmaker(), wsgienv, start_response)
       
    19 
       
    20 class _wsgioutputfile(object):
       
    21     def __init__(self, request):
       
    22         self.request = request
       
    23 
       
    24     def write(self, data):
       
    25         self.request.write(data)
       
    26     def writelines(self, lines):
       
    27         for line in lines:
       
    28             self.write(line)
       
    29     def flush(self):
       
    30         return None
       
    31     def close(self):
       
    32         return None
       
    33 
       
    34 class _wsgirequest(object):
       
    35     def __init__(self, destination, wsgienv, start_response):
       
    36         version = wsgienv['wsgi.version']
       
    37         if (version < (1,0)) or (version >= (2, 0)):
       
    38             raise RuntimeError("Unknown and unsupported WSGI version %d.%d" \
       
    39                                % version)
       
    40         self.inp = wsgienv['wsgi.input']
       
    41         self.out = _wsgioutputfile(self)
       
    42         self.server_write = None
       
    43         self.err = wsgienv['wsgi.errors']
       
    44         self.threaded = wsgienv['wsgi.multithread']
       
    45         self.multiprocess = wsgienv['wsgi.multiprocess']
       
    46         self.run_once = wsgienv['wsgi.run_once']
       
    47         self.env = wsgienv
    18         self.form = cgi.parse(self.inp, self.env, keep_blank_values=1)
    48         self.form = cgi.parse(self.inp, self.env, keep_blank_values=1)
    19         self.will_close = True
    49         self.start_response = start_response
       
    50         self.headers = []
       
    51         destination.run(self)
       
    52 
       
    53     def __iter__(self):
       
    54         return iter([])
    20 
    55 
    21     def read(self, count=-1):
    56     def read(self, count=-1):
    22         return self.inp.read(count)
    57         return self.inp.read(count)
    23 
    58 
    24     def write(self, *things):
    59     def write(self, *things):
       
    60         if self.server_write is None:
       
    61             if not self.headers:
       
    62                 raise RuntimeError("request.write called before headers sent.")
       
    63             self.server_write = self.start_response('200 Script output follows',
       
    64                                                     self.headers)
       
    65             self.start_response = None
       
    66             self.headers = None
    25         for thing in things:
    67         for thing in things:
    26             if hasattr(thing, "__iter__"):
    68             if hasattr(thing, "__iter__"):
    27                 for part in thing:
    69                 for part in thing:
    28                     self.write(part)
    70                     self.write(part)
    29             else:
    71             else:
    30                 try:
    72                 try:
    31                     self.out.write(str(thing))
    73                     self.server_write(str(thing))
    32                 except socket.error, inst:
    74                 except socket.error, inst:
    33                     if inst[0] != errno.ECONNRESET:
    75                     if inst[0] != errno.ECONNRESET:
    34                         raise
    76                         raise
    35 
    77 
    36     def done(self):
       
    37         if self.will_close:
       
    38             self.inp.close()
       
    39             self.out.close()
       
    40         else:
       
    41             self.out.flush()
       
    42 
       
    43     def header(self, headers=[('Content-type','text/html')]):
    78     def header(self, headers=[('Content-type','text/html')]):
    44         for header in headers:
    79         self.headers.extend(headers)
    45             self.out.write("%s: %s\r\n" % header)
       
    46         self.out.write("\r\n")
       
    47 
    80 
    48     def httphdr(self, type, filename=None, length=0, headers={}):
    81     def httphdr(self, type, filename=None, length=0, headers={}):
    49         headers = headers.items()
    82         headers = headers.items()
    50         headers.append(('Content-type', type))
    83         headers.append(('Content-type', type))
    51         if filename:
    84         if filename:
    52             headers.append(('Content-disposition', 'attachment; filename=%s' %
    85             headers.append(('Content-disposition', 'attachment; filename=%s' %
    53                             filename))
    86                             filename))
    54         # we do not yet support http 1.1 chunked transfer, so we have
       
    55         # to force connection to close if content-length not known
       
    56         if length:
    87         if length:
    57             headers.append(('Content-length', str(length)))
    88             headers.append(('Content-length', str(length)))
    58             self.will_close = False
       
    59         else:
       
    60             headers.append(('Connection', 'close'))
       
    61             self.will_close = True
       
    62         self.header(headers)
    89         self.header(headers)