##// END OF EJS Templates
hgweb: fix errors spotted by pychecker
Benoit Boissinot -
r3130:2e043c9a default
parent child Browse files
Show More
@@ -1,225 +1,225
1 1 # hgweb/server.py - The standalone hg web server.
2 2 #
3 3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
5 5 #
6 6 # This software may be used and distributed according to the terms
7 7 # of the GNU General Public License, incorporated herein by reference.
8 8
9 9 from mercurial.demandload import demandload
10 10 import os, sys, errno
11 11 demandload(globals(), "urllib BaseHTTPServer socket SocketServer")
12 12 demandload(globals(), "mercurial:ui,hg,util,templater")
13 13 demandload(globals(), "hgweb_mod:hgweb hgwebdir_mod:hgwebdir request:wsgiapplication")
14 14 from mercurial.i18n import gettext as _
15 15
16 16 def _splitURI(uri):
17 17 """ Return path and query splited from uri
18 18
19 19 Just like CGI environment, the path is unquoted, the query is
20 20 not.
21 21 """
22 22 if '?' in uri:
23 23 path, query = uri.split('?', 1)
24 24 else:
25 25 path, query = uri, ''
26 26 return urllib.unquote(path), query
27 27
28 28 class _error_logger(object):
29 29 def __init__(self, handler):
30 30 self.handler = handler
31 31 def flush(self):
32 32 pass
33 def write(str):
33 def write(self, str):
34 34 self.writelines(str.split('\n'))
35 def writelines(seq):
35 def writelines(self, seq):
36 36 for msg in seq:
37 37 self.handler.log_error("HG error: %s", msg)
38 38
39 39 class _hgwebhandler(object, BaseHTTPServer.BaseHTTPRequestHandler):
40 40 def __init__(self, *args, **kargs):
41 41 self.protocol_version = 'HTTP/1.1'
42 42 BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kargs)
43 43
44 44 def log_error(self, format, *args):
45 45 errorlog = self.server.errorlog
46 46 errorlog.write("%s - - [%s] %s\n" % (self.address_string(),
47 47 self.log_date_time_string(),
48 48 format % args))
49 49
50 50 def log_message(self, format, *args):
51 51 accesslog = self.server.accesslog
52 52 accesslog.write("%s - - [%s] %s\n" % (self.address_string(),
53 53 self.log_date_time_string(),
54 54 format % args))
55 55
56 56 def do_POST(self):
57 57 try:
58 58 self.do_hgweb()
59 59 except socket.error, inst:
60 60 if inst[0] != errno.EPIPE:
61 61 raise
62 62
63 63 def do_GET(self):
64 64 self.do_POST()
65 65
66 66 def do_hgweb(self):
67 67 path_info, query = _splitURI(self.path)
68 68
69 69 env = {}
70 70 env['GATEWAY_INTERFACE'] = 'CGI/1.1'
71 71 env['REQUEST_METHOD'] = self.command
72 72 env['SERVER_NAME'] = self.server.server_name
73 73 env['SERVER_PORT'] = str(self.server.server_port)
74 74 env['REQUEST_URI'] = "/"
75 75 env['PATH_INFO'] = path_info
76 76 if query:
77 77 env['QUERY_STRING'] = query
78 78 host = self.address_string()
79 79 if host != self.client_address[0]:
80 80 env['REMOTE_HOST'] = host
81 81 env['REMOTE_ADDR'] = self.client_address[0]
82 82
83 83 if self.headers.typeheader is None:
84 84 env['CONTENT_TYPE'] = self.headers.type
85 85 else:
86 86 env['CONTENT_TYPE'] = self.headers.typeheader
87 87 length = self.headers.getheader('content-length')
88 88 if length:
89 89 env['CONTENT_LENGTH'] = length
90 90 for header in [h for h in self.headers.keys() \
91 91 if h not in ('content-type', 'content-length')]:
92 92 hkey = 'HTTP_' + header.replace('-', '_').upper()
93 93 hval = self.headers.getheader(header)
94 94 hval = hval.replace('\n', '').strip()
95 95 if hval:
96 96 env[hkey] = hval
97 97 env['SERVER_PROTOCOL'] = self.request_version
98 98 env['wsgi.version'] = (1, 0)
99 99 env['wsgi.url_scheme'] = 'http'
100 100 env['wsgi.input'] = self.rfile
101 101 env['wsgi.errors'] = _error_logger(self)
102 102 env['wsgi.multithread'] = isinstance(self.server,
103 103 SocketServer.ThreadingMixIn)
104 104 env['wsgi.multiprocess'] = isinstance(self.server,
105 105 SocketServer.ForkingMixIn)
106 106 env['wsgi.run_once'] = 0
107 107
108 108 self.close_connection = True
109 109 self.saved_status = None
110 110 self.saved_headers = []
111 111 self.sent_headers = False
112 112 self.length = None
113 113 req = self.server.reqmaker(env, self._start_response)
114 114 for data in req:
115 115 if data:
116 116 self._write(data)
117 117
118 118 def send_headers(self):
119 119 if not self.saved_status:
120 120 raise AssertionError("Sending headers before start_response() called")
121 121 saved_status = self.saved_status.split(None, 1)
122 122 saved_status[0] = int(saved_status[0])
123 123 self.send_response(*saved_status)
124 124 should_close = True
125 125 for h in self.saved_headers:
126 126 self.send_header(*h)
127 127 if h[0].lower() == 'content-length':
128 128 should_close = False
129 129 self.length = int(h[1])
130 130 # The value of the Connection header is a list of case-insensitive
131 131 # tokens separated by commas and optional whitespace.
132 132 if 'close' in [token.strip().lower() for token in
133 133 self.headers.get('connection', '').split(',')]:
134 134 should_close = True
135 135 if should_close:
136 136 self.send_header('Connection', 'close')
137 137 self.close_connection = should_close
138 138 self.end_headers()
139 139 self.sent_headers = True
140 140
141 141 def _start_response(self, http_status, headers, exc_info=None):
142 142 code, msg = http_status.split(None, 1)
143 143 code = int(code)
144 144 self.saved_status = http_status
145 145 bad_headers = ('connection', 'transfer-encoding')
146 146 self.saved_headers = [ h for h in headers \
147 147 if h[0].lower() not in bad_headers ]
148 148 return self._write
149 149
150 150 def _write(self, data):
151 151 if not self.saved_status:
152 152 raise AssertionError("data written before start_response() called")
153 153 elif not self.sent_headers:
154 154 self.send_headers()
155 155 if self.length is not None:
156 156 if len(data) > self.length:
157 157 raise AssertionError("Content-length header sent, but more bytes than specified are being written.")
158 158 self.length = self.length - len(data)
159 159 self.wfile.write(data)
160 160 self.wfile.flush()
161 161
162 162 def create_server(ui, repo):
163 163 use_threads = True
164 164
165 165 def openlog(opt, default):
166 166 if opt and opt != '-':
167 167 return open(opt, 'w')
168 168 return default
169 169
170 170 address = ui.config("web", "address", "")
171 171 port = int(ui.config("web", "port", 8000))
172 172 use_ipv6 = ui.configbool("web", "ipv6")
173 173 webdir_conf = ui.config("web", "webdir_conf")
174 174 accesslog = openlog(ui.config("web", "accesslog", "-"), sys.stdout)
175 175 errorlog = openlog(ui.config("web", "errorlog", "-"), sys.stderr)
176 176
177 177 if use_threads:
178 178 try:
179 179 from threading import activeCount
180 180 except ImportError:
181 181 use_threads = False
182 182
183 183 if use_threads:
184 184 _mixin = SocketServer.ThreadingMixIn
185 185 else:
186 186 if hasattr(os, "fork"):
187 187 _mixin = SocketServer.ForkingMixIn
188 188 else:
189 189 class _mixin: pass
190 190
191 191 class MercurialHTTPServer(object, _mixin, BaseHTTPServer.HTTPServer):
192 192 def __init__(self, *args, **kargs):
193 193 BaseHTTPServer.HTTPServer.__init__(self, *args, **kargs)
194 194 self.accesslog = accesslog
195 195 self.errorlog = errorlog
196 196 self.repo = repo
197 197 self.webdir_conf = webdir_conf
198 198 self.webdirmaker = hgwebdir
199 199 self.repoviewmaker = hgweb
200 200 self.reqmaker = wsgiapplication(self.make_handler)
201 201 self.daemon_threads = True
202 202
203 203 def make_handler(self):
204 204 if self.webdir_conf:
205 205 hgwebobj = self.webdirmaker(self.webdir_conf)
206 206 elif self.repo is not None:
207 207 hgwebobj = self.repoviewmaker(repo.__class__(repo.ui,
208 208 repo.origroot))
209 209 else:
210 210 raise hg.RepoError(_("There is no Mercurial repository here"
211 211 " (.hg not found)"))
212 212 return hgwebobj
213 213
214 214 class IPv6HTTPServer(MercurialHTTPServer):
215 215 address_family = getattr(socket, 'AF_INET6', None)
216 216
217 217 def __init__(self, *args, **kwargs):
218 218 if self.address_family is None:
219 219 raise hg.RepoError(_('IPv6 not available on this system'))
220 220 super(IPv6HTTPServer, self).__init__(*args, **kwargs)
221 221
222 222 if use_ipv6:
223 223 return IPv6HTTPServer((address, port), _hgwebhandler)
224 224 else:
225 225 return MercurialHTTPServer((address, port), _hgwebhandler)
General Comments 0
You need to be logged in to leave comments. Login now