Mercurial > public > mercurial-scm > hg
comparison mercurial/hgweb/server.py @ 37788:ed5448edcbfa stable 4.6rc0
merge with default to begin 4.6 freeze
# no-check-commit because of many vendored packages
author | Augie Fackler <augie@google.com> |
---|---|
date | Wed, 18 Apr 2018 15:32:08 -0400 |
parents | 7de7bd407251 b5ca5d34fe8d |
children | 9f499d28efb4 |
comparison
equal
deleted
inserted
replaced
37287:fb92df8b634c | 37788:ed5448edcbfa |
---|---|
11 import errno | 11 import errno |
12 import os | 12 import os |
13 import socket | 13 import socket |
14 import sys | 14 import sys |
15 import traceback | 15 import traceback |
16 import wsgiref.validate | |
16 | 17 |
17 from ..i18n import _ | 18 from ..i18n import _ |
18 | 19 |
19 from .. import ( | 20 from .. import ( |
20 encoding, | 21 encoding, |
109 # r-string. This is the easy way out. | 110 # r-string. This is the easy way out. |
110 newline = chr(10) | 111 newline = chr(10) |
111 self.log_error(r"Exception happened during processing " | 112 self.log_error(r"Exception happened during processing " |
112 r"request '%s':%s%s", self.path, newline, tb) | 113 r"request '%s':%s%s", self.path, newline, tb) |
113 | 114 |
115 def do_PUT(self): | |
116 self.do_POST() | |
117 | |
114 def do_GET(self): | 118 def do_GET(self): |
115 self.do_POST() | 119 self.do_POST() |
116 | 120 |
117 def do_hgweb(self): | 121 def do_hgweb(self): |
118 self.sent_headers = False | 122 self.sent_headers = False |
130 env[r'GATEWAY_INTERFACE'] = r'CGI/1.1' | 134 env[r'GATEWAY_INTERFACE'] = r'CGI/1.1' |
131 env[r'REQUEST_METHOD'] = self.command | 135 env[r'REQUEST_METHOD'] = self.command |
132 env[r'SERVER_NAME'] = self.server.server_name | 136 env[r'SERVER_NAME'] = self.server.server_name |
133 env[r'SERVER_PORT'] = str(self.server.server_port) | 137 env[r'SERVER_PORT'] = str(self.server.server_port) |
134 env[r'REQUEST_URI'] = self.path | 138 env[r'REQUEST_URI'] = self.path |
135 env[r'SCRIPT_NAME'] = self.server.prefix | 139 env[r'SCRIPT_NAME'] = pycompat.sysstr(self.server.prefix) |
136 env[r'PATH_INFO'] = path[len(self.server.prefix):] | 140 env[r'PATH_INFO'] = pycompat.sysstr(path[len(self.server.prefix):]) |
137 env[r'REMOTE_HOST'] = self.client_address[0] | 141 env[r'REMOTE_HOST'] = self.client_address[0] |
138 env[r'REMOTE_ADDR'] = self.client_address[0] | 142 env[r'REMOTE_ADDR'] = self.client_address[0] |
139 if query: | 143 env[r'QUERY_STRING'] = query or r'' |
140 env[r'QUERY_STRING'] = query | |
141 | 144 |
142 if pycompat.ispy3: | 145 if pycompat.ispy3: |
143 if self.headers.get_content_type() is None: | 146 if self.headers.get_content_type() is None: |
144 env[r'CONTENT_TYPE'] = self.headers.get_default_type() | 147 env[r'CONTENT_TYPE'] = self.headers.get_default_type() |
145 else: | 148 else: |
146 env[r'CONTENT_TYPE'] = self.headers.get_content_type() | 149 env[r'CONTENT_TYPE'] = self.headers.get_content_type() |
147 length = self.headers.get('content-length') | 150 length = self.headers.get(r'content-length') |
148 else: | 151 else: |
149 if self.headers.typeheader is None: | 152 if self.headers.typeheader is None: |
150 env[r'CONTENT_TYPE'] = self.headers.type | 153 env[r'CONTENT_TYPE'] = self.headers.type |
151 else: | 154 else: |
152 env[r'CONTENT_TYPE'] = self.headers.typeheader | 155 env[r'CONTENT_TYPE'] = self.headers.typeheader |
153 length = self.headers.getheader('content-length') | 156 length = self.headers.getheader(r'content-length') |
154 if length: | 157 if length: |
155 env[r'CONTENT_LENGTH'] = length | 158 env[r'CONTENT_LENGTH'] = length |
156 for header in [h for h in self.headers.keys() | 159 for header in [h for h in self.headers.keys() |
157 if h not in ('content-type', 'content-length')]: | 160 if h not in (r'content-type', r'content-length')]: |
158 hkey = r'HTTP_' + header.replace(r'-', r'_').upper() | 161 hkey = r'HTTP_' + header.replace(r'-', r'_').upper() |
159 hval = self.headers.get(header) | 162 hval = self.headers.get(header) |
160 hval = hval.replace(r'\n', r'').strip() | 163 hval = hval.replace(r'\n', r'').strip() |
161 if hval: | 164 if hval: |
162 env[hkey] = hval | 165 env[hkey] = hval |
163 env[r'SERVER_PROTOCOL'] = self.request_version | 166 env[r'SERVER_PROTOCOL'] = self.request_version |
164 env[r'wsgi.version'] = (1, 0) | 167 env[r'wsgi.version'] = (1, 0) |
165 env[r'wsgi.url_scheme'] = self.url_scheme | 168 env[r'wsgi.url_scheme'] = pycompat.sysstr(self.url_scheme) |
166 if env.get(r'HTTP_EXPECT', '').lower() == '100-continue': | 169 if env.get(r'HTTP_EXPECT', '').lower() == '100-continue': |
167 self.rfile = common.continuereader(self.rfile, self.wfile.write) | 170 self.rfile = common.continuereader(self.rfile, self.wfile.write) |
168 | 171 |
169 env[r'wsgi.input'] = self.rfile | 172 env[r'wsgi.input'] = self.rfile |
170 env[r'wsgi.errors'] = _error_logger(self) | 173 env[r'wsgi.errors'] = _error_logger(self) |
171 env[r'wsgi.multithread'] = isinstance(self.server, | 174 env[r'wsgi.multithread'] = isinstance(self.server, |
172 socketserver.ThreadingMixIn) | 175 socketserver.ThreadingMixIn) |
173 env[r'wsgi.multiprocess'] = isinstance(self.server, | 176 env[r'wsgi.multiprocess'] = isinstance(self.server, |
174 socketserver.ForkingMixIn) | 177 socketserver.ForkingMixIn) |
175 env[r'wsgi.run_once'] = 0 | 178 env[r'wsgi.run_once'] = 0 |
179 | |
180 wsgiref.validate.check_environ(env) | |
176 | 181 |
177 self.saved_status = None | 182 self.saved_status = None |
178 self.saved_headers = [] | 183 self.saved_headers = [] |
179 self.length = None | 184 self.length = None |
180 self._chunked = None | 185 self._chunked = None |
235 def _done(self): | 240 def _done(self): |
236 if self._chunked: | 241 if self._chunked: |
237 self.wfile.write('0\r\n\r\n') | 242 self.wfile.write('0\r\n\r\n') |
238 self.wfile.flush() | 243 self.wfile.flush() |
239 | 244 |
245 def version_string(self): | |
246 if self.server.serverheader: | |
247 return self.server.serverheader | |
248 return httpservermod.basehttprequesthandler.version_string(self) | |
249 | |
240 class _httprequesthandlerssl(_httprequesthandler): | 250 class _httprequesthandlerssl(_httprequesthandler): |
241 """HTTPS handler based on Python's ssl module""" | 251 """HTTPS handler based on Python's ssl module""" |
242 | 252 |
243 url_scheme = 'https' | 253 url_scheme = 'https' |
244 | 254 |
263 cafile=cafile, | 273 cafile=cafile, |
264 requireclientcert=reqcert) | 274 requireclientcert=reqcert) |
265 | 275 |
266 def setup(self): | 276 def setup(self): |
267 self.connection = self.request | 277 self.connection = self.request |
268 self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) | 278 self.rfile = self.request.makefile(r"rb", self.rbufsize) |
269 self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) | 279 self.wfile = self.request.makefile(r"wb", self.wbufsize) |
270 | 280 |
271 try: | 281 try: |
272 import threading | 282 import threading |
273 threading.activeCount() # silence pyflakes and bypass demandimport | 283 threading.activeCount() # silence pyflakes and bypass demandimport |
274 _mixin = socketserver.ThreadingMixIn | 284 _mixin = socketserver.ThreadingMixIn |
279 class _mixin(object): | 289 class _mixin(object): |
280 pass | 290 pass |
281 | 291 |
282 def openlog(opt, default): | 292 def openlog(opt, default): |
283 if opt and opt != '-': | 293 if opt and opt != '-': |
284 return open(opt, 'a') | 294 return open(opt, 'ab') |
285 return default | 295 return default |
286 | 296 |
287 class MercurialHTTPServer(_mixin, httpservermod.httpserver, object): | 297 class MercurialHTTPServer(_mixin, httpservermod.httpserver, object): |
288 | 298 |
289 # SO_REUSEADDR has broken semantics on windows | 299 # SO_REUSEADDR has broken semantics on windows |
307 self.accesslog = alog | 317 self.accesslog = alog |
308 self.errorlog = elog | 318 self.errorlog = elog |
309 | 319 |
310 self.addr, self.port = self.socket.getsockname()[0:2] | 320 self.addr, self.port = self.socket.getsockname()[0:2] |
311 self.fqaddr = socket.getfqdn(addr[0]) | 321 self.fqaddr = socket.getfqdn(addr[0]) |
322 | |
323 self.serverheader = ui.config('web', 'server-header') | |
312 | 324 |
313 class IPv6HTTPServer(MercurialHTTPServer): | 325 class IPv6HTTPServer(MercurialHTTPServer): |
314 address_family = getattr(socket, 'AF_INET6', None) | 326 address_family = getattr(socket, 'AF_INET6', None) |
315 def __init__(self, *args, **kwargs): | 327 def __init__(self, *args, **kwargs): |
316 if self.address_family is None: | 328 if self.address_family is None: |