request.py
90 lines
| 3.2 KiB
| text/x-python
|
PythonLexer
|
r2391 | # hgweb/request.py - An http request from either CGI or the standalone server. | ||
|
r2355 | # | ||
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net> | ||||
# Copyright 2005 Matt Mackall <mpm@selenic.com> | ||||
# | ||||
# This software may be used and distributed according to the terms | ||||
# of the GNU General Public License, incorporated herein by reference. | ||||
from mercurial.demandload import demandload | ||||
|
r2394 | demandload(globals(), "socket sys cgi os errno") | ||
|
r2355 | from mercurial.i18n import gettext as _ | ||
|
r2506 | class wsgiapplication(object): | ||
def __init__(self, destmaker): | ||||
self.destmaker = destmaker | ||||
def __call__(self, wsgienv, start_response): | ||||
return _wsgirequest(self.destmaker(), wsgienv, start_response) | ||||
class _wsgioutputfile(object): | ||||
def __init__(self, request): | ||||
self.request = request | ||||
def write(self, data): | ||||
self.request.write(data) | ||||
def writelines(self, lines): | ||||
for line in lines: | ||||
self.write(line) | ||||
def flush(self): | ||||
return None | ||||
def close(self): | ||||
return None | ||||
class _wsgirequest(object): | ||||
def __init__(self, destination, wsgienv, start_response): | ||||
version = wsgienv['wsgi.version'] | ||||
if (version < (1,0)) or (version >= (2, 0)): | ||||
raise RuntimeError("Unknown and unsupported WSGI version %d.%d" \ | ||||
% version) | ||||
self.inp = wsgienv['wsgi.input'] | ||||
self.out = _wsgioutputfile(self) | ||||
self.server_write = None | ||||
self.err = wsgienv['wsgi.errors'] | ||||
self.threaded = wsgienv['wsgi.multithread'] | ||||
self.multiprocess = wsgienv['wsgi.multiprocess'] | ||||
self.run_once = wsgienv['wsgi.run_once'] | ||||
self.env = wsgienv | ||||
|
r2355 | self.form = cgi.parse(self.inp, self.env, keep_blank_values=1) | ||
|
r2506 | self.start_response = start_response | ||
self.headers = [] | ||||
|
r2535 | destination.run_wsgi(self) | ||
|
r2506 | |||
def __iter__(self): | ||||
return iter([]) | ||||
|
r2355 | |||
|
r2464 | def read(self, count=-1): | ||
return self.inp.read(count) | ||||
|
r2355 | def write(self, *things): | ||
for thing in things: | ||||
if hasattr(thing, "__iter__"): | ||||
for part in thing: | ||||
self.write(part) | ||||
else: | ||||
|
r2514 | thing = str(thing) | ||
if self.server_write is None: | ||||
if not self.headers: | ||||
raise RuntimeError("request.write called before headers sent (%s)." % thing) | ||||
self.server_write = self.start_response('200 Script output follows', | ||||
self.headers) | ||||
self.start_response = None | ||||
self.headers = None | ||||
|
r2355 | try: | ||
|
r2514 | self.server_write(thing) | ||
|
r2355 | except socket.error, inst: | ||
if inst[0] != errno.ECONNRESET: | ||||
raise | ||||
def header(self, headers=[('Content-type','text/html')]): | ||||
|
r2506 | self.headers.extend(headers) | ||
|
r2355 | |||
|
r2466 | def httphdr(self, type, filename=None, length=0, headers={}): | ||
headers = headers.items() | ||||
headers.append(('Content-type', type)) | ||||
|
r2434 | if filename: | ||
headers.append(('Content-disposition', 'attachment; filename=%s' % | ||||
filename)) | ||||
if length: | ||||
headers.append(('Content-length', str(length))) | ||||
|
r2355 | self.header(headers) | ||