##// END OF EJS Templates
hgweb: commit forgotten update to a3d7f99c23c0
Dirkjan Ochtman -
r7742:fceb9fa0 default
parent child Browse files
Show More
@@ -1,134 +1,134 b''
1 # hgweb/request.py - An http request from either CGI or the standalone server.
1 # hgweb/request.py - An http request from either CGI or the standalone server.
2 #
2 #
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
5 #
5 #
6 # This software may be used and distributed according to the terms
6 # This software may be used and distributed according to the terms
7 # of the GNU General Public License, incorporated herein by reference.
7 # of the GNU General Public License, incorporated herein by reference.
8
8
9 import socket, cgi, errno
9 import socket, cgi, errno
10 from mercurial import util
10 from mercurial import util
11 from common import ErrorResponse, statusmessage
11 from common import ErrorResponse, statusmessage
12
12
13 shortcuts = {
13 shortcuts = {
14 'cl': [('cmd', ['changelog']), ('rev', None)],
14 'cl': [('cmd', ['changelog']), ('rev', None)],
15 'sl': [('cmd', ['shortlog']), ('rev', None)],
15 'sl': [('cmd', ['shortlog']), ('rev', None)],
16 'cs': [('cmd', ['changeset']), ('node', None)],
16 'cs': [('cmd', ['changeset']), ('node', None)],
17 'f': [('cmd', ['file']), ('filenode', None)],
17 'f': [('cmd', ['file']), ('filenode', None)],
18 'fl': [('cmd', ['filelog']), ('filenode', None)],
18 'fl': [('cmd', ['filelog']), ('filenode', None)],
19 'fd': [('cmd', ['filediff']), ('node', None)],
19 'fd': [('cmd', ['filediff']), ('node', None)],
20 'fa': [('cmd', ['annotate']), ('filenode', None)],
20 'fa': [('cmd', ['annotate']), ('filenode', None)],
21 'mf': [('cmd', ['manifest']), ('manifest', None)],
21 'mf': [('cmd', ['manifest']), ('manifest', None)],
22 'ca': [('cmd', ['archive']), ('node', None)],
22 'ca': [('cmd', ['archive']), ('node', None)],
23 'tags': [('cmd', ['tags'])],
23 'tags': [('cmd', ['tags'])],
24 'tip': [('cmd', ['changeset']), ('node', ['tip'])],
24 'tip': [('cmd', ['changeset']), ('node', ['tip'])],
25 'static': [('cmd', ['static']), ('file', None)]
25 'static': [('cmd', ['static']), ('file', None)]
26 }
26 }
27
27
28 def expand(form):
28 def expand(form):
29 for k in shortcuts.iterkeys():
29 for k in shortcuts.iterkeys():
30 if k in form:
30 if k in form:
31 for name, value in shortcuts[k]:
31 for name, value in shortcuts[k]:
32 if value is None:
32 if value is None:
33 value = form[k]
33 value = form[k]
34 form[name] = value
34 form[name] = value
35 del form[k]
35 del form[k]
36 return form
36 return form
37
37
38 class wsgirequest(object):
38 class wsgirequest(object):
39 def __init__(self, wsgienv, start_response):
39 def __init__(self, wsgienv, start_response):
40 version = wsgienv['wsgi.version']
40 version = wsgienv['wsgi.version']
41 if (version < (1, 0)) or (version >= (2, 0)):
41 if (version < (1, 0)) or (version >= (2, 0)):
42 raise RuntimeError("Unknown and unsupported WSGI version %d.%d"
42 raise RuntimeError("Unknown and unsupported WSGI version %d.%d"
43 % version)
43 % version)
44 self.inp = wsgienv['wsgi.input']
44 self.inp = wsgienv['wsgi.input']
45 self.err = wsgienv['wsgi.errors']
45 self.err = wsgienv['wsgi.errors']
46 self.threaded = wsgienv['wsgi.multithread']
46 self.threaded = wsgienv['wsgi.multithread']
47 self.multiprocess = wsgienv['wsgi.multiprocess']
47 self.multiprocess = wsgienv['wsgi.multiprocess']
48 self.run_once = wsgienv['wsgi.run_once']
48 self.run_once = wsgienv['wsgi.run_once']
49 self.env = wsgienv
49 self.env = wsgienv
50 self.form = expand(cgi.parse(self.inp, self.env, keep_blank_values=1))
50 self.form = expand(cgi.parse(self.inp, self.env, keep_blank_values=1))
51 self._start_response = start_response
51 self._start_response = start_response
52 self.server_write = None
52 self.server_write = None
53 self.headers = []
53 self.headers = []
54
54
55 def __iter__(self):
55 def __iter__(self):
56 return iter([])
56 return iter([])
57
57
58 def read(self, count=-1):
58 def read(self, count=-1):
59 return self.inp.read(count)
59 return self.inp.read(count)
60
60
61 def drain(self):
61 def drain(self):
62 '''need to read all data from request, httplib is half-duplex'''
62 '''need to read all data from request, httplib is half-duplex'''
63 length = int(self.env.get('CONTENT_LENGTH', 0))
63 length = int(self.env.get('CONTENT_LENGTH', 0))
64 for s in util.filechunkiter(self.inp, limit=length):
64 for s in util.filechunkiter(self.inp, limit=length):
65 pass
65 pass
66
66
67 def respond(self, status, type=None, filename=None, length=0):
67 def respond(self, status, type=None, filename=None, length=0):
68 if self._start_response is not None:
68 if self._start_response is not None:
69
69
70 self.httphdr(type, filename, length)
70 self.httphdr(type, filename, length)
71 if not self.headers:
71 if not self.headers:
72 raise RuntimeError("request.write called before headers sent")
72 raise RuntimeError("request.write called before headers sent")
73
73
74 for k, v in self.headers:
74 for k, v in self.headers:
75 if not isinstance(v, str):
75 if not isinstance(v, str):
76 raise TypeError('header value must be string: %r' % v)
76 raise TypeError('header value must be string: %r' % v)
77
77
78 if isinstance(status, ErrorResponse):
78 if isinstance(status, ErrorResponse):
79 self.header(status.headers)
79 status = statusmessage(status.code)
80 status = statusmessage(status.code)
80 self.header(status.headers)
81 elif status == 200:
81 elif status == 200:
82 status = '200 Script output follows'
82 status = '200 Script output follows'
83 elif isinstance(status, int):
83 elif isinstance(status, int):
84 status = statusmessage(status)
84 status = statusmessage(status)
85
85
86 self.server_write = self._start_response(status, self.headers)
86 self.server_write = self._start_response(status, self.headers)
87 self._start_response = None
87 self._start_response = None
88 self.headers = []
88 self.headers = []
89
89
90 def write(self, thing):
90 def write(self, thing):
91 if hasattr(thing, "__iter__"):
91 if hasattr(thing, "__iter__"):
92 for part in thing:
92 for part in thing:
93 self.write(part)
93 self.write(part)
94 else:
94 else:
95 thing = str(thing)
95 thing = str(thing)
96 try:
96 try:
97 self.server_write(thing)
97 self.server_write(thing)
98 except socket.error, inst:
98 except socket.error, inst:
99 if inst[0] != errno.ECONNRESET:
99 if inst[0] != errno.ECONNRESET:
100 raise
100 raise
101
101
102 def writelines(self, lines):
102 def writelines(self, lines):
103 for line in lines:
103 for line in lines:
104 self.write(line)
104 self.write(line)
105
105
106 def flush(self):
106 def flush(self):
107 return None
107 return None
108
108
109 def close(self):
109 def close(self):
110 return None
110 return None
111
111
112 def header(self, headers=[('Content-Type','text/html')]):
112 def header(self, headers=[('Content-Type','text/html')]):
113 self.headers.extend(headers)
113 self.headers.extend(headers)
114
114
115 def httphdr(self, type=None, filename=None, length=0, headers={}):
115 def httphdr(self, type=None, filename=None, length=0, headers={}):
116 headers = headers.items()
116 headers = headers.items()
117 if type is not None:
117 if type is not None:
118 headers.append(('Content-Type', type))
118 headers.append(('Content-Type', type))
119 if filename:
119 if filename:
120 filename = (filename.split('/')[-1]
120 filename = (filename.split('/')[-1]
121 .replace('\\', '\\\\').replace('"', '\\"'))
121 .replace('\\', '\\\\').replace('"', '\\"'))
122 headers.append(('Content-Disposition',
122 headers.append(('Content-Disposition',
123 'inline; filename="%s"' % filename))
123 'inline; filename="%s"' % filename))
124 if length:
124 if length:
125 headers.append(('Content-Length', str(length)))
125 headers.append(('Content-Length', str(length)))
126 self.header(headers)
126 self.header(headers)
127
127
128 def wsgiapplication(app_maker):
128 def wsgiapplication(app_maker):
129 '''For compatibility with old CGI scripts. A plain hgweb() or hgwebdir()
129 '''For compatibility with old CGI scripts. A plain hgweb() or hgwebdir()
130 can and should now be used as a WSGI application.'''
130 can and should now be used as a WSGI application.'''
131 application = app_maker()
131 application = app_maker()
132 def run_wsgi(env, respond):
132 def run_wsgi(env, respond):
133 return application(env, respond)
133 return application(env, respond)
134 return run_wsgi
134 return run_wsgi
General Comments 0
You need to be logged in to leave comments. Login now