##// END OF EJS Templates
configitems: register the 'web.errorlog' config
Boris Feld -
r34237:c97a750c default
parent child Browse files
Show More
@@ -1,641 +1,644 b''
1 1 # configitems.py - centralized declaration of configuration option
2 2 #
3 3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import functools
11 11
12 12 from . import (
13 13 encoding,
14 14 error,
15 15 )
16 16
17 17 def loadconfigtable(ui, extname, configtable):
18 18 """update config item known to the ui with the extension ones"""
19 19 for section, items in configtable.items():
20 20 knownitems = ui._knownconfig.setdefault(section, {})
21 21 knownkeys = set(knownitems)
22 22 newkeys = set(items)
23 23 for key in sorted(knownkeys & newkeys):
24 24 msg = "extension '%s' overwrite config item '%s.%s'"
25 25 msg %= (extname, section, key)
26 26 ui.develwarn(msg, config='warn-config')
27 27
28 28 knownitems.update(items)
29 29
30 30 class configitem(object):
31 31 """represent a known config item
32 32
33 33 :section: the official config section where to find this item,
34 34 :name: the official name within the section,
35 35 :default: default value for this item,
36 36 :alias: optional list of tuples as alternatives.
37 37 """
38 38
39 39 def __init__(self, section, name, default=None, alias=()):
40 40 self.section = section
41 41 self.name = name
42 42 self.default = default
43 43 self.alias = list(alias)
44 44
45 45 coreitems = {}
46 46
47 47 def _register(configtable, *args, **kwargs):
48 48 item = configitem(*args, **kwargs)
49 49 section = configtable.setdefault(item.section, {})
50 50 if item.name in section:
51 51 msg = "duplicated config item registration for '%s.%s'"
52 52 raise error.ProgrammingError(msg % (item.section, item.name))
53 53 section[item.name] = item
54 54
55 55 # special value for case where the default is derived from other values
56 56 dynamicdefault = object()
57 57
58 58 # Registering actual config items
59 59
60 60 def getitemregister(configtable):
61 61 return functools.partial(_register, configtable)
62 62
63 63 coreconfigitem = getitemregister(coreitems)
64 64
65 65 coreconfigitem('auth', 'cookiefile',
66 66 default=None,
67 67 )
68 68 # bookmarks.pushing: internal hack for discovery
69 69 coreconfigitem('bookmarks', 'pushing',
70 70 default=list,
71 71 )
72 72 # bundle.mainreporoot: internal hack for bundlerepo
73 73 coreconfigitem('bundle', 'mainreporoot',
74 74 default='',
75 75 )
76 76 # bundle.reorder: experimental config
77 77 coreconfigitem('bundle', 'reorder',
78 78 default='auto',
79 79 )
80 80 coreconfigitem('censor', 'policy',
81 81 default='abort',
82 82 )
83 83 coreconfigitem('chgserver', 'idletimeout',
84 84 default=3600,
85 85 )
86 86 coreconfigitem('chgserver', 'skiphash',
87 87 default=False,
88 88 )
89 89 coreconfigitem('cmdserver', 'log',
90 90 default=None,
91 91 )
92 92 coreconfigitem('color', 'mode',
93 93 default='auto',
94 94 )
95 95 coreconfigitem('color', 'pagermode',
96 96 default=dynamicdefault,
97 97 )
98 98 coreconfigitem('commands', 'status.relative',
99 99 default=False,
100 100 )
101 101 coreconfigitem('commands', 'status.skipstates',
102 102 default=[],
103 103 )
104 104 coreconfigitem('commands', 'status.verbose',
105 105 default=False,
106 106 )
107 107 coreconfigitem('commands', 'update.requiredest',
108 108 default=False,
109 109 )
110 110 coreconfigitem('devel', 'all-warnings',
111 111 default=False,
112 112 )
113 113 coreconfigitem('devel', 'bundle2.debug',
114 114 default=False,
115 115 )
116 116 coreconfigitem('devel', 'check-locks',
117 117 default=False,
118 118 )
119 119 coreconfigitem('devel', 'check-relroot',
120 120 default=False,
121 121 )
122 122 coreconfigitem('devel', 'default-date',
123 123 default=None,
124 124 )
125 125 coreconfigitem('devel', 'deprec-warn',
126 126 default=False,
127 127 )
128 128 coreconfigitem('devel', 'disableloaddefaultcerts',
129 129 default=False,
130 130 )
131 131 coreconfigitem('devel', 'legacy.exchange',
132 132 default=list,
133 133 )
134 134 coreconfigitem('devel', 'servercafile',
135 135 default='',
136 136 )
137 137 coreconfigitem('devel', 'serverexactprotocol',
138 138 default='',
139 139 )
140 140 coreconfigitem('devel', 'serverrequirecert',
141 141 default=False,
142 142 )
143 143 coreconfigitem('devel', 'strip-obsmarkers',
144 144 default=True,
145 145 )
146 146 coreconfigitem('email', 'charsets',
147 147 default=list,
148 148 )
149 149 coreconfigitem('email', 'method',
150 150 default='smtp',
151 151 )
152 152 coreconfigitem('experimental', 'bundle-phases',
153 153 default=False,
154 154 )
155 155 coreconfigitem('experimental', 'bundle2-advertise',
156 156 default=True,
157 157 )
158 158 coreconfigitem('experimental', 'bundle2-output-capture',
159 159 default=False,
160 160 )
161 161 coreconfigitem('experimental', 'bundle2.pushback',
162 162 default=False,
163 163 )
164 164 coreconfigitem('experimental', 'bundle2lazylocking',
165 165 default=False,
166 166 )
167 167 coreconfigitem('experimental', 'bundlecomplevel',
168 168 default=None,
169 169 )
170 170 coreconfigitem('experimental', 'changegroup3',
171 171 default=False,
172 172 )
173 173 coreconfigitem('experimental', 'clientcompressionengines',
174 174 default=list,
175 175 )
176 176 coreconfigitem('experimental', 'copytrace',
177 177 default='on',
178 178 )
179 179 coreconfigitem('experimental', 'crecordtest',
180 180 default=None,
181 181 )
182 182 coreconfigitem('experimental', 'editortmpinhg',
183 183 default=False,
184 184 )
185 185 coreconfigitem('experimental', 'stabilization',
186 186 default=list,
187 187 alias=[('experimental', 'evolution')],
188 188 )
189 189 coreconfigitem('experimental', 'stabilization.bundle-obsmarker',
190 190 default=False,
191 191 alias=[('experimental', 'evolution.bundle-obsmarker')],
192 192 )
193 193 coreconfigitem('experimental', 'stabilization.track-operation',
194 194 default=False,
195 195 alias=[('experimental', 'evolution.track-operation')]
196 196 )
197 197 coreconfigitem('experimental', 'exportableenviron',
198 198 default=list,
199 199 )
200 200 coreconfigitem('experimental', 'extendedheader.index',
201 201 default=None,
202 202 )
203 203 coreconfigitem('experimental', 'extendedheader.similarity',
204 204 default=False,
205 205 )
206 206 coreconfigitem('experimental', 'format.compression',
207 207 default='zlib',
208 208 )
209 209 coreconfigitem('experimental', 'graphshorten',
210 210 default=False,
211 211 )
212 212 coreconfigitem('experimental', 'hook-track-tags',
213 213 default=False,
214 214 )
215 215 coreconfigitem('experimental', 'httppostargs',
216 216 default=False,
217 217 )
218 218 coreconfigitem('experimental', 'manifestv2',
219 219 default=False,
220 220 )
221 221 coreconfigitem('experimental', 'mergedriver',
222 222 default=None,
223 223 )
224 224 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
225 225 default=False,
226 226 )
227 227 coreconfigitem('experimental', 'rebase.multidest',
228 228 default=False,
229 229 )
230 230 coreconfigitem('experimental', 'revertalternateinteractivemode',
231 231 default=True,
232 232 )
233 233 coreconfigitem('experimental', 'revlogv2',
234 234 default=None,
235 235 )
236 236 coreconfigitem('experimental', 'spacemovesdown',
237 237 default=False,
238 238 )
239 239 coreconfigitem('experimental', 'treemanifest',
240 240 default=False,
241 241 )
242 242 coreconfigitem('experimental', 'updatecheck',
243 243 default=None,
244 244 )
245 245 coreconfigitem('format', 'aggressivemergedeltas',
246 246 default=False,
247 247 )
248 248 coreconfigitem('format', 'chunkcachesize',
249 249 default=None,
250 250 )
251 251 coreconfigitem('format', 'dotencode',
252 252 default=True,
253 253 )
254 254 coreconfigitem('format', 'generaldelta',
255 255 default=False,
256 256 )
257 257 coreconfigitem('format', 'manifestcachesize',
258 258 default=None,
259 259 )
260 260 coreconfigitem('format', 'maxchainlen',
261 261 default=None,
262 262 )
263 263 coreconfigitem('format', 'obsstore-version',
264 264 default=None,
265 265 )
266 266 coreconfigitem('format', 'usefncache',
267 267 default=True,
268 268 )
269 269 coreconfigitem('format', 'usegeneraldelta',
270 270 default=True,
271 271 )
272 272 coreconfigitem('format', 'usestore',
273 273 default=True,
274 274 )
275 275 coreconfigitem('hostsecurity', 'ciphers',
276 276 default=None,
277 277 )
278 278 coreconfigitem('hostsecurity', 'disabletls10warning',
279 279 default=False,
280 280 )
281 281 coreconfigitem('http_proxy', 'always',
282 282 default=False,
283 283 )
284 284 coreconfigitem('http_proxy', 'host',
285 285 default=None,
286 286 )
287 287 coreconfigitem('http_proxy', 'no',
288 288 default=list,
289 289 )
290 290 coreconfigitem('http_proxy', 'passwd',
291 291 default=None,
292 292 )
293 293 coreconfigitem('http_proxy', 'user',
294 294 default=None,
295 295 )
296 296 coreconfigitem('merge', 'followcopies',
297 297 default=True,
298 298 )
299 299 coreconfigitem('pager', 'ignore',
300 300 default=list,
301 301 )
302 302 coreconfigitem('patch', 'eol',
303 303 default='strict',
304 304 )
305 305 coreconfigitem('patch', 'fuzz',
306 306 default=2,
307 307 )
308 308 coreconfigitem('paths', 'default',
309 309 default=None,
310 310 )
311 311 coreconfigitem('paths', 'default-push',
312 312 default=None,
313 313 )
314 314 coreconfigitem('phases', 'checksubrepos',
315 315 default='follow',
316 316 )
317 317 coreconfigitem('phases', 'publish',
318 318 default=True,
319 319 )
320 320 coreconfigitem('profiling', 'enabled',
321 321 default=False,
322 322 )
323 323 coreconfigitem('profiling', 'format',
324 324 default='text',
325 325 )
326 326 coreconfigitem('profiling', 'freq',
327 327 default=1000,
328 328 )
329 329 coreconfigitem('profiling', 'limit',
330 330 default=30,
331 331 )
332 332 coreconfigitem('profiling', 'nested',
333 333 default=0,
334 334 )
335 335 coreconfigitem('profiling', 'sort',
336 336 default='inlinetime',
337 337 )
338 338 coreconfigitem('profiling', 'statformat',
339 339 default='hotpath',
340 340 )
341 341 coreconfigitem('progress', 'assume-tty',
342 342 default=False,
343 343 )
344 344 coreconfigitem('progress', 'changedelay',
345 345 default=1,
346 346 )
347 347 coreconfigitem('progress', 'clear-complete',
348 348 default=True,
349 349 )
350 350 coreconfigitem('progress', 'debug',
351 351 default=False,
352 352 )
353 353 coreconfigitem('progress', 'delay',
354 354 default=3,
355 355 )
356 356 coreconfigitem('progress', 'disable',
357 357 default=False,
358 358 )
359 359 coreconfigitem('progress', 'estimate',
360 360 default=2,
361 361 )
362 362 coreconfigitem('progress', 'refresh',
363 363 default=0.1,
364 364 )
365 365 coreconfigitem('progress', 'width',
366 366 default=dynamicdefault,
367 367 )
368 368 coreconfigitem('push', 'pushvars.server',
369 369 default=False,
370 370 )
371 371 coreconfigitem('server', 'bundle1',
372 372 default=True,
373 373 )
374 374 coreconfigitem('server', 'bundle1gd',
375 375 default=None,
376 376 )
377 377 coreconfigitem('server', 'compressionengines',
378 378 default=list,
379 379 )
380 380 coreconfigitem('server', 'concurrent-push-mode',
381 381 default='strict',
382 382 )
383 383 coreconfigitem('server', 'disablefullbundle',
384 384 default=False,
385 385 )
386 386 coreconfigitem('server', 'maxhttpheaderlen',
387 387 default=1024,
388 388 )
389 389 coreconfigitem('server', 'preferuncompressed',
390 390 default=False,
391 391 )
392 392 coreconfigitem('server', 'uncompressed',
393 393 default=True,
394 394 )
395 395 coreconfigitem('server', 'uncompressedallowsecret',
396 396 default=False,
397 397 )
398 398 coreconfigitem('server', 'validate',
399 399 default=False,
400 400 )
401 401 coreconfigitem('server', 'zliblevel',
402 402 default=-1,
403 403 )
404 404 coreconfigitem('smtp', 'host',
405 405 default=None,
406 406 )
407 407 coreconfigitem('smtp', 'local_hostname',
408 408 default=None,
409 409 )
410 410 coreconfigitem('smtp', 'password',
411 411 default=None,
412 412 )
413 413 coreconfigitem('smtp', 'tls',
414 414 default='none',
415 415 )
416 416 coreconfigitem('smtp', 'username',
417 417 default=None,
418 418 )
419 419 coreconfigitem('sparse', 'missingwarning',
420 420 default=True,
421 421 )
422 422 coreconfigitem('trusted', 'groups',
423 423 default=list,
424 424 )
425 425 coreconfigitem('trusted', 'users',
426 426 default=list,
427 427 )
428 428 coreconfigitem('ui', '_usedassubrepo',
429 429 default=False,
430 430 )
431 431 coreconfigitem('ui', 'allowemptycommit',
432 432 default=False,
433 433 )
434 434 coreconfigitem('ui', 'archivemeta',
435 435 default=True,
436 436 )
437 437 coreconfigitem('ui', 'askusername',
438 438 default=False,
439 439 )
440 440 coreconfigitem('ui', 'clonebundlefallback',
441 441 default=False,
442 442 )
443 443 coreconfigitem('ui', 'clonebundleprefers',
444 444 default=list,
445 445 )
446 446 coreconfigitem('ui', 'clonebundles',
447 447 default=True,
448 448 )
449 449 coreconfigitem('ui', 'color',
450 450 default='auto',
451 451 )
452 452 coreconfigitem('ui', 'commitsubrepos',
453 453 default=False,
454 454 )
455 455 coreconfigitem('ui', 'debug',
456 456 default=False,
457 457 )
458 458 coreconfigitem('ui', 'debugger',
459 459 default=None,
460 460 )
461 461 coreconfigitem('ui', 'fallbackencoding',
462 462 default=None,
463 463 )
464 464 coreconfigitem('ui', 'forcecwd',
465 465 default=None,
466 466 )
467 467 coreconfigitem('ui', 'forcemerge',
468 468 default=None,
469 469 )
470 470 coreconfigitem('ui', 'formatdebug',
471 471 default=False,
472 472 )
473 473 coreconfigitem('ui', 'formatjson',
474 474 default=False,
475 475 )
476 476 coreconfigitem('ui', 'formatted',
477 477 default=None,
478 478 )
479 479 coreconfigitem('ui', 'graphnodetemplate',
480 480 default=None,
481 481 )
482 482 coreconfigitem('ui', 'http2debuglevel',
483 483 default=None,
484 484 )
485 485 coreconfigitem('ui', 'interactive',
486 486 default=None,
487 487 )
488 488 coreconfigitem('ui', 'interface',
489 489 default=None,
490 490 )
491 491 coreconfigitem('ui', 'logblockedtimes',
492 492 default=False,
493 493 )
494 494 coreconfigitem('ui', 'logtemplate',
495 495 default=None,
496 496 )
497 497 coreconfigitem('ui', 'merge',
498 498 default=None,
499 499 )
500 500 coreconfigitem('ui', 'mergemarkers',
501 501 default='basic',
502 502 )
503 503 coreconfigitem('ui', 'mergemarkertemplate',
504 504 default=('{node|short} '
505 505 '{ifeq(tags, "tip", "", '
506 506 'ifeq(tags, "", "", "{tags} "))}'
507 507 '{if(bookmarks, "{bookmarks} ")}'
508 508 '{ifeq(branch, "default", "", "{branch} ")}'
509 509 '- {author|user}: {desc|firstline}')
510 510 )
511 511 coreconfigitem('ui', 'nontty',
512 512 default=False,
513 513 )
514 514 coreconfigitem('ui', 'origbackuppath',
515 515 default=None,
516 516 )
517 517 coreconfigitem('ui', 'paginate',
518 518 default=True,
519 519 )
520 520 coreconfigitem('ui', 'patch',
521 521 default=None,
522 522 )
523 523 coreconfigitem('ui', 'portablefilenames',
524 524 default='warn',
525 525 )
526 526 coreconfigitem('ui', 'promptecho',
527 527 default=False,
528 528 )
529 529 coreconfigitem('ui', 'quiet',
530 530 default=False,
531 531 )
532 532 coreconfigitem('ui', 'quietbookmarkmove',
533 533 default=False,
534 534 )
535 535 coreconfigitem('ui', 'remotecmd',
536 536 default='hg',
537 537 )
538 538 coreconfigitem('ui', 'report_untrusted',
539 539 default=True,
540 540 )
541 541 coreconfigitem('ui', 'rollback',
542 542 default=True,
543 543 )
544 544 coreconfigitem('ui', 'slash',
545 545 default=False,
546 546 )
547 547 coreconfigitem('ui', 'ssh',
548 548 default='ssh',
549 549 )
550 550 coreconfigitem('ui', 'statuscopies',
551 551 default=False,
552 552 )
553 553 coreconfigitem('ui', 'strict',
554 554 default=False,
555 555 )
556 556 coreconfigitem('ui', 'style',
557 557 default='',
558 558 )
559 559 coreconfigitem('ui', 'supportcontact',
560 560 default=None,
561 561 )
562 562 coreconfigitem('ui', 'textwidth',
563 563 default=78,
564 564 )
565 565 coreconfigitem('ui', 'timeout',
566 566 default='600',
567 567 )
568 568 coreconfigitem('ui', 'traceback',
569 569 default=False,
570 570 )
571 571 coreconfigitem('ui', 'tweakdefaults',
572 572 default=False,
573 573 )
574 574 coreconfigitem('ui', 'usehttp2',
575 575 default=False,
576 576 )
577 577 coreconfigitem('ui', 'username',
578 578 alias=[('ui', 'user')]
579 579 )
580 580 coreconfigitem('ui', 'verbose',
581 581 default=False,
582 582 )
583 583 coreconfigitem('verify', 'skipflags',
584 584 default=None,
585 585 )
586 586 coreconfigitem('web', 'accesslog',
587 587 default='-',
588 588 )
589 589 coreconfigitem('web', 'address',
590 590 default='',
591 591 )
592 592 coreconfigitem('web', 'allow_archive',
593 593 default=list,
594 594 )
595 595 coreconfigitem('web', 'allow_read',
596 596 default=list,
597 597 )
598 598 coreconfigitem('web', 'baseurl',
599 599 default=None,
600 600 )
601 601 coreconfigitem('web', 'cacerts',
602 602 default=None,
603 603 )
604 604 coreconfigitem('web', 'certificate',
605 605 default=None,
606 606 )
607 607 coreconfigitem('web', 'collapse',
608 608 default=False,
609 609 )
610 610 coreconfigitem('web', 'csp',
611 611 default=None,
612 612 )
613 613 coreconfigitem('web', 'deny_read',
614 614 default=list,
615 615 )
616 616 coreconfigitem('web', 'descend',
617 617 default=True,
618 618 )
619 619 coreconfigitem('web', 'description',
620 620 default="",
621 621 )
622 622 coreconfigitem('web', 'encoding',
623 623 default=lambda: encoding.encoding,
624 624 )
625 coreconfigitem('web', 'errorlog',
626 default='-',
627 )
625 628 coreconfigitem('worker', 'backgroundclose',
626 629 default=dynamicdefault,
627 630 )
628 631 # Windows defaults to a limit of 512 open files. A buffer of 128
629 632 # should give us enough headway.
630 633 coreconfigitem('worker', 'backgroundclosemaxqueue',
631 634 default=384,
632 635 )
633 636 coreconfigitem('worker', 'backgroundcloseminfilecount',
634 637 default=2048,
635 638 )
636 639 coreconfigitem('worker', 'backgroundclosethreadcount',
637 640 default=4,
638 641 )
639 642 coreconfigitem('worker', 'numcpus',
640 643 default=None,
641 644 )
@@ -1,335 +1,335 b''
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-2007 Matt Mackall <mpm@selenic.com>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 from __future__ import absolute_import
10 10
11 11 import errno
12 12 import os
13 13 import socket
14 14 import sys
15 15 import traceback
16 16
17 17 from ..i18n import _
18 18
19 19 from .. import (
20 20 error,
21 21 pycompat,
22 22 util,
23 23 )
24 24
25 25 httpservermod = util.httpserver
26 26 socketserver = util.socketserver
27 27 urlerr = util.urlerr
28 28 urlreq = util.urlreq
29 29
30 30 from . import (
31 31 common,
32 32 )
33 33
34 34 def _splitURI(uri):
35 35 """Return path and query that has been split from uri
36 36
37 37 Just like CGI environment, the path is unquoted, the query is
38 38 not.
39 39 """
40 40 if '?' in uri:
41 41 path, query = uri.split('?', 1)
42 42 else:
43 43 path, query = uri, ''
44 44 return urlreq.unquote(path), query
45 45
46 46 class _error_logger(object):
47 47 def __init__(self, handler):
48 48 self.handler = handler
49 49 def flush(self):
50 50 pass
51 51 def write(self, str):
52 52 self.writelines(str.split('\n'))
53 53 def writelines(self, seq):
54 54 for msg in seq:
55 55 self.handler.log_error("HG error: %s", msg)
56 56
57 57 class _httprequesthandler(httpservermod.basehttprequesthandler):
58 58
59 59 url_scheme = 'http'
60 60
61 61 @staticmethod
62 62 def preparehttpserver(httpserver, ui):
63 63 """Prepare .socket of new HTTPServer instance"""
64 64 pass
65 65
66 66 def __init__(self, *args, **kargs):
67 67 self.protocol_version = 'HTTP/1.1'
68 68 httpservermod.basehttprequesthandler.__init__(self, *args, **kargs)
69 69
70 70 def _log_any(self, fp, format, *args):
71 71 fp.write("%s - - [%s] %s\n" % (self.client_address[0],
72 72 self.log_date_time_string(),
73 73 format % args))
74 74 fp.flush()
75 75
76 76 def log_error(self, format, *args):
77 77 self._log_any(self.server.errorlog, format, *args)
78 78
79 79 def log_message(self, format, *args):
80 80 self._log_any(self.server.accesslog, format, *args)
81 81
82 82 def log_request(self, code='-', size='-'):
83 83 xheaders = []
84 84 if util.safehasattr(self, 'headers'):
85 85 xheaders = [h for h in self.headers.items()
86 86 if h[0].startswith('x-')]
87 87 self.log_message('"%s" %s %s%s',
88 88 self.requestline, str(code), str(size),
89 89 ''.join([' %s:%s' % h for h in sorted(xheaders)]))
90 90
91 91 def do_write(self):
92 92 try:
93 93 self.do_hgweb()
94 94 except socket.error as inst:
95 95 if inst[0] != errno.EPIPE:
96 96 raise
97 97
98 98 def do_POST(self):
99 99 try:
100 100 self.do_write()
101 101 except Exception:
102 102 self._start_response("500 Internal Server Error", [])
103 103 self._write("Internal Server Error")
104 104 self._done()
105 105 tb = "".join(traceback.format_exception(*sys.exc_info()))
106 106 self.log_error("Exception happened during processing "
107 107 "request '%s':\n%s", self.path, tb)
108 108
109 109 def do_GET(self):
110 110 self.do_POST()
111 111
112 112 def do_hgweb(self):
113 113 path, query = _splitURI(self.path)
114 114
115 115 env = {}
116 116 env['GATEWAY_INTERFACE'] = 'CGI/1.1'
117 117 env['REQUEST_METHOD'] = self.command
118 118 env['SERVER_NAME'] = self.server.server_name
119 119 env['SERVER_PORT'] = str(self.server.server_port)
120 120 env['REQUEST_URI'] = self.path
121 121 env['SCRIPT_NAME'] = self.server.prefix
122 122 env['PATH_INFO'] = path[len(self.server.prefix):]
123 123 env['REMOTE_HOST'] = self.client_address[0]
124 124 env['REMOTE_ADDR'] = self.client_address[0]
125 125 if query:
126 126 env['QUERY_STRING'] = query
127 127
128 128 if self.headers.typeheader is None:
129 129 env['CONTENT_TYPE'] = self.headers.type
130 130 else:
131 131 env['CONTENT_TYPE'] = self.headers.typeheader
132 132 length = self.headers.getheader('content-length')
133 133 if length:
134 134 env['CONTENT_LENGTH'] = length
135 135 for header in [h for h in self.headers.keys()
136 136 if h not in ('content-type', 'content-length')]:
137 137 hkey = 'HTTP_' + header.replace('-', '_').upper()
138 138 hval = self.headers.getheader(header)
139 139 hval = hval.replace('\n', '').strip()
140 140 if hval:
141 141 env[hkey] = hval
142 142 env['SERVER_PROTOCOL'] = self.request_version
143 143 env['wsgi.version'] = (1, 0)
144 144 env['wsgi.url_scheme'] = self.url_scheme
145 145 if env.get('HTTP_EXPECT', '').lower() == '100-continue':
146 146 self.rfile = common.continuereader(self.rfile, self.wfile.write)
147 147
148 148 env['wsgi.input'] = self.rfile
149 149 env['wsgi.errors'] = _error_logger(self)
150 150 env['wsgi.multithread'] = isinstance(self.server,
151 151 socketserver.ThreadingMixIn)
152 152 env['wsgi.multiprocess'] = isinstance(self.server,
153 153 socketserver.ForkingMixIn)
154 154 env['wsgi.run_once'] = 0
155 155
156 156 self.saved_status = None
157 157 self.saved_headers = []
158 158 self.sent_headers = False
159 159 self.length = None
160 160 self._chunked = None
161 161 for chunk in self.server.application(env, self._start_response):
162 162 self._write(chunk)
163 163 if not self.sent_headers:
164 164 self.send_headers()
165 165 self._done()
166 166
167 167 def send_headers(self):
168 168 if not self.saved_status:
169 169 raise AssertionError("Sending headers before "
170 170 "start_response() called")
171 171 saved_status = self.saved_status.split(None, 1)
172 172 saved_status[0] = int(saved_status[0])
173 173 self.send_response(*saved_status)
174 174 self.length = None
175 175 self._chunked = False
176 176 for h in self.saved_headers:
177 177 self.send_header(*h)
178 178 if h[0].lower() == 'content-length':
179 179 self.length = int(h[1])
180 180 if (self.length is None and
181 181 saved_status[0] != common.HTTP_NOT_MODIFIED):
182 182 self._chunked = (not self.close_connection and
183 183 self.request_version == "HTTP/1.1")
184 184 if self._chunked:
185 185 self.send_header('Transfer-Encoding', 'chunked')
186 186 else:
187 187 self.send_header('Connection', 'close')
188 188 self.end_headers()
189 189 self.sent_headers = True
190 190
191 191 def _start_response(self, http_status, headers, exc_info=None):
192 192 code, msg = http_status.split(None, 1)
193 193 code = int(code)
194 194 self.saved_status = http_status
195 195 bad_headers = ('connection', 'transfer-encoding')
196 196 self.saved_headers = [h for h in headers
197 197 if h[0].lower() not in bad_headers]
198 198 return self._write
199 199
200 200 def _write(self, data):
201 201 if not self.saved_status:
202 202 raise AssertionError("data written before start_response() called")
203 203 elif not self.sent_headers:
204 204 self.send_headers()
205 205 if self.length is not None:
206 206 if len(data) > self.length:
207 207 raise AssertionError("Content-length header sent, but more "
208 208 "bytes than specified are being written.")
209 209 self.length = self.length - len(data)
210 210 elif self._chunked and data:
211 211 data = '%x\r\n%s\r\n' % (len(data), data)
212 212 self.wfile.write(data)
213 213 self.wfile.flush()
214 214
215 215 def _done(self):
216 216 if self._chunked:
217 217 self.wfile.write('0\r\n\r\n')
218 218 self.wfile.flush()
219 219
220 220 class _httprequesthandlerssl(_httprequesthandler):
221 221 """HTTPS handler based on Python's ssl module"""
222 222
223 223 url_scheme = 'https'
224 224
225 225 @staticmethod
226 226 def preparehttpserver(httpserver, ui):
227 227 try:
228 228 from .. import sslutil
229 229 sslutil.modernssl
230 230 except ImportError:
231 231 raise error.Abort(_("SSL support is unavailable"))
232 232
233 233 certfile = ui.config('web', 'certificate')
234 234
235 235 # These config options are currently only meant for testing. Use
236 236 # at your own risk.
237 237 cafile = ui.config('devel', 'servercafile')
238 238 reqcert = ui.configbool('devel', 'serverrequirecert')
239 239
240 240 httpserver.socket = sslutil.wrapserversocket(httpserver.socket,
241 241 ui,
242 242 certfile=certfile,
243 243 cafile=cafile,
244 244 requireclientcert=reqcert)
245 245
246 246 def setup(self):
247 247 self.connection = self.request
248 248 self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
249 249 self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
250 250
251 251 try:
252 252 import threading
253 253 threading.activeCount() # silence pyflakes and bypass demandimport
254 254 _mixin = socketserver.ThreadingMixIn
255 255 except ImportError:
256 256 if util.safehasattr(os, "fork"):
257 257 _mixin = socketserver.ForkingMixIn
258 258 else:
259 259 class _mixin(object):
260 260 pass
261 261
262 262 def openlog(opt, default):
263 263 if opt and opt != '-':
264 264 return open(opt, 'a')
265 265 return default
266 266
267 267 class MercurialHTTPServer(_mixin, httpservermod.httpserver, object):
268 268
269 269 # SO_REUSEADDR has broken semantics on windows
270 270 if pycompat.osname == 'nt':
271 271 allow_reuse_address = 0
272 272
273 273 def __init__(self, ui, app, addr, handler, **kwargs):
274 274 httpservermod.httpserver.__init__(self, addr, handler, **kwargs)
275 275 self.daemon_threads = True
276 276 self.application = app
277 277
278 278 handler.preparehttpserver(self, ui)
279 279
280 280 prefix = ui.config('web', 'prefix', '')
281 281 if prefix:
282 282 prefix = '/' + prefix.strip('/')
283 283 self.prefix = prefix
284 284
285 285 alog = openlog(ui.config('web', 'accesslog'), ui.fout)
286 elog = openlog(ui.config('web', 'errorlog', '-'), ui.ferr)
286 elog = openlog(ui.config('web', 'errorlog'), ui.ferr)
287 287 self.accesslog = alog
288 288 self.errorlog = elog
289 289
290 290 self.addr, self.port = self.socket.getsockname()[0:2]
291 291 self.fqaddr = socket.getfqdn(addr[0])
292 292
293 293 class IPv6HTTPServer(MercurialHTTPServer):
294 294 address_family = getattr(socket, 'AF_INET6', None)
295 295 def __init__(self, *args, **kwargs):
296 296 if self.address_family is None:
297 297 raise error.RepoError(_('IPv6 is not available on this system'))
298 298 super(IPv6HTTPServer, self).__init__(*args, **kwargs)
299 299
300 300 def create_server(ui, app):
301 301
302 302 if ui.config('web', 'certificate'):
303 303 handler = _httprequesthandlerssl
304 304 else:
305 305 handler = _httprequesthandler
306 306
307 307 if ui.configbool('web', 'ipv6'):
308 308 cls = IPv6HTTPServer
309 309 else:
310 310 cls = MercurialHTTPServer
311 311
312 312 # ugly hack due to python issue5853 (for threaded use)
313 313 try:
314 314 import mimetypes
315 315 mimetypes.init()
316 316 except UnicodeDecodeError:
317 317 # Python 2.x's mimetypes module attempts to decode strings
318 318 # from Windows' ANSI APIs as ascii (fail), then re-encode them
319 319 # as ascii (clown fail), because the default Python Unicode
320 320 # codec is hardcoded as ascii.
321 321
322 322 sys.argv # unwrap demand-loader so that reload() works
323 323 reload(sys) # resurrect sys.setdefaultencoding()
324 324 oldenc = sys.getdefaultencoding()
325 325 sys.setdefaultencoding("latin1") # or any full 8-bit encoding
326 326 mimetypes.init()
327 327 sys.setdefaultencoding(oldenc)
328 328
329 329 address = ui.config('web', 'address')
330 330 port = util.getport(ui.config('web', 'port', 8000))
331 331 try:
332 332 return cls(ui, app, (address, port), handler)
333 333 except socket.error as inst:
334 334 raise error.Abort(_("cannot start server at '%s:%d': %s")
335 335 % (address, port, inst.args[1]))
General Comments 0
You need to be logged in to leave comments. Login now