comparison MoinMoin/support/werkzeug/serving.py @ 6129:7f12cf241d5e

update werkzeug to 0.12.1, update CHANGES
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Tue, 11 Apr 2017 22:42:23 +0200
parents 9f12f41504fc
children df65dcf7daea
comparison
equal deleted inserted replaced
6128:561b7a9c2bd9 6129:7f12cf241d5e
39 39
40 import os 40 import os
41 import socket 41 import socket
42 import sys 42 import sys
43 import signal 43 import signal
44
45
46 can_fork = hasattr(os, "fork")
47
48
49 try:
50 import termcolor
51 except ImportError:
52 termcolor = None
44 53
45 try: 54 try:
46 import ssl 55 import ssl
47 except ImportError: 56 except ImportError:
48 class _SslDummy(object): 57 class _SslDummy(object):
60 else: 69 else:
61 return crypto 70 return crypto
62 71
63 72
64 try: 73 try:
65 from SocketServer import ThreadingMixIn, ForkingMixIn 74 import SocketServer as socketserver
66 from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler 75 from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
67 except ImportError: 76 except ImportError:
68 from socketserver import ThreadingMixIn, ForkingMixIn 77 import socketserver
69 from http.server import HTTPServer, BaseHTTPRequestHandler 78 from http.server import HTTPServer, BaseHTTPRequestHandler
79
80 ThreadingMixIn = socketserver.ThreadingMixIn
81
82 if can_fork:
83 ForkingMixIn = socketserver.ForkingMixIn
84 else:
85 class ForkingMixIn(object):
86 pass
70 87
71 # important: do not use relative imports here or python -m will break 88 # important: do not use relative imports here or python -m will break
72 import werkzeug 89 import werkzeug
73 from werkzeug._internal import _log 90 from werkzeug._internal import _log
74 from werkzeug._compat import PY2, reraise, wsgi_encoding_dance 91 from werkzeug._compat import PY2, WIN, reraise, wsgi_encoding_dance
75 from werkzeug.urls import url_parse, url_unquote 92 from werkzeug.urls import url_parse, url_unquote
76 from werkzeug.exceptions import InternalServerError 93 from werkzeug.exceptions import InternalServerError
77 94
78 95
79 LISTEN_QUEUE = 128 96 LISTEN_QUEUE = 128
80 can_open_by_fd = hasattr(socket, 'fromfd') 97 can_open_by_fd = not WIN and hasattr(socket, 'fromfd')
81 98
82 99
83 class WSGIRequestHandler(BaseHTTPRequestHandler, object): 100 class WSGIRequestHandler(BaseHTTPRequestHandler, object):
84 101
85 """A request handler that implements WSGI dispatching.""" 102 """A request handler that implements WSGI dispatching."""
109 'SERVER_SOFTWARE': self.server_version, 126 'SERVER_SOFTWARE': self.server_version,
110 'REQUEST_METHOD': self.command, 127 'REQUEST_METHOD': self.command,
111 'SCRIPT_NAME': '', 128 'SCRIPT_NAME': '',
112 'PATH_INFO': wsgi_encoding_dance(path_info), 129 'PATH_INFO': wsgi_encoding_dance(path_info),
113 'QUERY_STRING': wsgi_encoding_dance(request_url.query), 130 'QUERY_STRING': wsgi_encoding_dance(request_url.query),
114 'CONTENT_TYPE': self.headers.get('Content-Type', ''),
115 'CONTENT_LENGTH': self.headers.get('Content-Length', ''),
116 'REMOTE_ADDR': self.address_string(), 131 'REMOTE_ADDR': self.address_string(),
117 'REMOTE_PORT': self.port_integer(), 132 'REMOTE_PORT': self.port_integer(),
118 'SERVER_NAME': self.server.server_address[0], 133 'SERVER_NAME': self.server.server_address[0],
119 'SERVER_PORT': str(self.server.server_address[1]), 134 'SERVER_PORT': str(self.server.server_address[1]),
120 'SERVER_PROTOCOL': self.request_version 135 'SERVER_PROTOCOL': self.request_version
121 } 136 }
122 137
123 for key, value in self.headers.items(): 138 for key, value in self.headers.items():
124 key = 'HTTP_' + key.upper().replace('-', '_') 139 key = key.upper().replace('-', '_')
125 if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'): 140 if key not in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
126 environ[key] = value 141 key = 'HTTP_' + key
142 environ[key] = value
127 143
128 if request_url.scheme and request_url.netloc: 144 if request_url.scheme and request_url.netloc:
129 environ['HTTP_HOST'] = request_url.netloc 145 environ['HTTP_HOST'] = request_url.netloc
130 146
131 return environ 147 return environ
267 283
268 def port_integer(self): 284 def port_integer(self):
269 return self.client_address[1] 285 return self.client_address[1]
270 286
271 def log_request(self, code='-', size='-'): 287 def log_request(self, code='-', size='-'):
272 self.log('info', '"%s" %s %s', self.requestline, code, size) 288 msg = self.requestline
289 code = str(code)
290
291 if termcolor:
292 color = termcolor.colored
293
294 if code[0] == '1': # 1xx - Informational
295 msg = color(msg, attrs=['bold'])
296 if code[0] == '2': # 2xx - Success
297 msg = color(msg, color='white')
298 elif code == '304': # 304 - Resource Not Modified
299 msg = color(msg, color='cyan')
300 elif code[0] == '3': # 3xx - Redirection
301 msg = color(msg, color='green')
302 elif code == '404': # 404 - Resource Not Found
303 msg = color(msg, color='yellow')
304 elif code[0] == '4': # 4xx - Client Error
305 msg = color(msg, color='red', attrs=['bold'])
306 else: # 5xx, or any other response
307 msg = color(msg, color='magenta', attrs=['bold'])
308
309 self.log('info', '"%s" %s %s', msg, code, size)
273 310
274 def log_error(self, *args): 311 def log_error(self, *args):
275 self.log('error', *args) 312 self.log('error', *args)
276 313
277 def log_message(self, format, *args): 314 def log_message(self, format, *args):
307 issuer = cert.get_issuer() 344 issuer = cert.get_issuer()
308 issuer.CN = 'Untrusted Authority' 345 issuer.CN = 'Untrusted Authority'
309 issuer.O = 'Self-Signed' 346 issuer.O = 'Self-Signed'
310 347
311 pkey = crypto.PKey() 348 pkey = crypto.PKey()
312 pkey.generate_key(crypto.TYPE_RSA, 1024) 349 pkey.generate_key(crypto.TYPE_RSA, 2048)
313 cert.set_pubkey(pkey) 350 cert.set_pubkey(pkey)
314 cert.sign(pkey, 'md5') 351 cert.sign(pkey, 'sha256')
315 352
316 return cert, pkey 353 return cert, pkey
317 354
318 355
319 def make_ssl_devcert(base_path, host=None, cn=None): 356 def make_ssl_devcert(base_path, host=None, cn=None):
464 HTTPServer.__init__(self, (host, int(port)), handler) 501 HTTPServer.__init__(self, (host, int(port)), handler)
465 self.app = app 502 self.app = app
466 self.passthrough_errors = passthrough_errors 503 self.passthrough_errors = passthrough_errors
467 self.shutdown_signal = False 504 self.shutdown_signal = False
468 self.host = host 505 self.host = host
469 self.port = port 506 self.port = self.socket.getsockname()[1]
470 507
471 # Patch in the original socket. 508 # Patch in the original socket.
472 if fd is not None: 509 if fd is not None:
473 self.socket.close() 510 self.socket.close()
474 self.socket = real_sock 511 self.socket = real_sock
514 551
515 class ThreadedWSGIServer(ThreadingMixIn, BaseWSGIServer): 552 class ThreadedWSGIServer(ThreadingMixIn, BaseWSGIServer):
516 553
517 """A WSGI server that does threading.""" 554 """A WSGI server that does threading."""
518 multithread = True 555 multithread = True
556 daemon_threads = True
519 557
520 558
521 class ForkingWSGIServer(ForkingMixIn, BaseWSGIServer): 559 class ForkingWSGIServer(ForkingMixIn, BaseWSGIServer):
522 560
523 """A WSGI server that does forking.""" 561 """A WSGI server that does forking."""
524 multiprocess = True 562 multiprocess = True
525 563
526 def __init__(self, host, port, app, processes=40, handler=None, 564 def __init__(self, host, port, app, processes=40, handler=None,
527 passthrough_errors=False, ssl_context=None, fd=None): 565 passthrough_errors=False, ssl_context=None, fd=None):
566 if not can_fork:
567 raise ValueError('Your platform does not support forking.')
528 BaseWSGIServer.__init__(self, host, port, app, handler, 568 BaseWSGIServer.__init__(self, host, port, app, handler,
529 passthrough_errors, ssl_context, fd) 569 passthrough_errors, ssl_context, fd)
530 self.max_children = processes 570 self.max_children = processes
531 571
532 572
685 s.listen(LISTEN_QUEUE) 725 s.listen(LISTEN_QUEUE)
686 log_startup(s) 726 log_startup(s)
687 else: 727 else:
688 s.close() 728 s.close()
689 729
690 from ._reloader import run_with_reloader 730 # Do not use relative imports, otherwise "python -m werkzeug.serving"
731 # breaks.
732 from werkzeug._reloader import run_with_reloader
691 run_with_reloader(inner, extra_files, reloader_interval, 733 run_with_reloader(inner, extra_files, reloader_interval,
692 reloader_type) 734 reloader_type)
693 else: 735 else:
694 inner() 736 inner()
695 737
696 738
697 def run_with_reloader(*args, **kwargs): 739 def run_with_reloader(*args, **kwargs):
698 # People keep using undocumented APIs. Do not use this function 740 # People keep using undocumented APIs. Do not use this function
699 # please, we do not guarantee that it continues working. 741 # please, we do not guarantee that it continues working.
700 from ._reloader import run_with_reloader 742 from werkzeug._reloader import run_with_reloader
701 return run_with_reloader(*args, **kwargs) 743 return run_with_reloader(*args, **kwargs)
702 744
703 745
704 def main(): 746 def main():
705 '''A simple command-line interface for :py:func:`run_simple`.''' 747 '''A simple command-line interface for :py:func:`run_simple`.'''