# -*- coding: utf-8 -*-"""werkzeug.serving~~~~~~~~~~~~~~~~There are many ways to serve a WSGI application. While you're developingit you usually don't want a full blown webserver like Apache but a simplestandalone one. From Python 2.5 onwards there is the `wsgiref`_ server inthe standard library. If you're using older versions of Python you candownload the package from the cheeseshop.However there are some caveats. Sourcecode won't reload itself whenchanged and each time you kill the server using ``^C`` you get an`KeyboardInterrupt` error. While the latter is easy to solve the firstone can be a pain in the ass in some situations.The easiest way is creating a small ``start-myproject.py`` that runs theapplication::#!/usr/bin/env python# -*- coding: utf-8 -*-from myproject import make_appfrom werkzeug.serving import run_simpleapp = make_app(...)run_simple('localhost', 8080, app, use_reloader=True)You can also pass it a `extra_files` keyword argument with a list ofadditional files (like configuration files) you want to observe.For bigger applications you should consider using `click`(http://click.pocoo.org) instead of a simple start file.:copyright: 2007 Pallets:license: BSD-3-Clause"""import ioimport osimport signalimport socketimport sysfrom datetime import datetime as dtfrom datetime import timedeltafrom ._compat import PY2from ._compat import reraisefrom ._compat import WINfrom ._compat import wsgi_encoding_dancefrom ._internal import _logfrom .exceptions import InternalServerErrorfrom .urls import uri_to_irifrom .urls import url_parsefrom .urls import url_unquotetry:import socketserverfrom http.server import BaseHTTPRequestHandlerfrom http.server import HTTPServerexcept ImportError:import SocketServer as socketserverfrom BaseHTTPServer import HTTPServerfrom BaseHTTPServer import BaseHTTPRequestHandlertry:import sslexcept ImportError:class _SslDummy(object):def __getattr__(self, name):raise RuntimeError("SSL support unavailable")ssl = _SslDummy()try:import clickexcept ImportError:click = NoneThreadingMixIn = socketserver.ThreadingMixIncan_fork = hasattr(os, "fork")if can_fork:ForkingMixIn = socketserver.ForkingMixInelse:class ForkingMixIn(object):passtry:af_unix = socket.AF_UNIXexcept AttributeError:af_unix = NoneLISTEN_QUEUE = 128can_open_by_fd = not WIN and hasattr(socket, "fromfd")# On Python 3, ConnectionError represents the same errnos as# socket.error from Python 2, while socket.error is an alias for the# more generic OSError.if PY2:_ConnectionError = socket.errorelse:_ConnectionError = ConnectionErrorclass DechunkedInput(io.RawIOBase):"""An input stream that handles Transfer-Encoding 'chunked'"""def __init__(self, rfile):self._rfile = rfileself._done = Falseself._len = 0def readable(self):return Truedef read_chunk_len(self):try:line = self._rfile.readline().decode("latin1")_len = int(line.strip(), 16)except ValueError:raise IOError("Invalid chunk header")if _len < 0:raise IOError("Negative chunk length not allowed")return _lendef readinto(self, buf):read = 0while not self._done and read < len(buf):if self._len == 0:# This is the first chunk or we fully consumed the previous# one. Read the next length of the next chunkself._len = self.read_chunk_len()if self._len == 0:# Found the final chunk of size 0. The stream is now exhausted,# but there is still a final newline that should be consumedself._done = Trueif self._len > 0:# There is data (left) in this chunk, so append it to the# buffer. If this operation fully consumes the chunk, this will# reset self._len to 0.n = min(len(buf), self._len)buf[read : read + n] = self._rfile.read(n)self._len -= nread += nif self._len == 0:# Skip the terminating newline of a chunk that has been fully# consumed. This also applies to the 0-sized final chunkterminator = self._rfile.readline()if terminator not in (b"\n", b"\r\n", b"\r"):raise IOError("Missing chunk terminating newline")return readclass WSGIRequestHandler(BaseHTTPRequestHandler, object):"""A request handler that implements WSGI dispatching."""@propertydef server_version(self):from . import __version__return "Werkzeug/" + __version__def make_environ(self):request_url = url_parse(self.path)def shutdown_server():self.server.shutdown_signal = Trueurl_scheme = "http" if self.server.ssl_context is None else "https"if not self.client_address:self.client_address = "<local>"if isinstance(self.client_address, str):self.client_address = (self.client_address, 0)else:pass# If there was no scheme but the path started with two slashes,# the first segment may have been incorrectly parsed as the# netloc, prepend it to the path again.if not request_url.scheme and request_url.netloc:path_info = "/%s%s" % (request_url.netloc, request_url.path)else:path_info = request_url.pathpath_info = url_unquote(path_info)environ = {"wsgi.version": (1, 0),"wsgi.url_scheme": url_scheme,"wsgi.input": self.rfile,"wsgi.errors": sys.stderr,"wsgi.multithread": self.server.multithread,"wsgi.multiprocess": self.server.multiprocess,"wsgi.run_once": False,"werkzeug.server.shutdown": shutdown_server,"SERVER_SOFTWARE": self.server_version,"REQUEST_METHOD": self.command,"SCRIPT_NAME": "","PATH_INFO": wsgi_encoding_dance(path_info),"QUERY_STRING": wsgi_encoding_dance(request_url.query),# Non-standard, added by mod_wsgi, uWSGI"REQUEST_URI": wsgi_encoding_dance(self.path),# Non-standard, added by gunicorn"RAW_URI": wsgi_encoding_dance(self.path),"REMOTE_ADDR": self.address_string(),"REMOTE_PORT": self.port_integer(),"SERVER_NAME": self.server.server_address[0],"SERVER_PORT": str(self.server.server_address[1]),"SERVER_PROTOCOL": self.request_version,}for key, value in self.get_header_items():key = key.upper().replace("-", "_")value = value.replace("\r\n", "")if key not in ("CONTENT_TYPE", "CONTENT_LENGTH"):key = "HTTP_" + keyif key in environ:value = "{},{}".format(environ[key], value)environ[key] = valueif environ.get("HTTP_TRANSFER_ENCODING", "").strip().lower() == "chunked":environ["wsgi.input_terminated"] = Trueenviron["wsgi.input"] = DechunkedInput(environ["wsgi.input"])# Per RFC 2616, if the URL is absolute, use that as the host.# We're using "has a scheme" to indicate an absolute URL.if request_url.scheme and request_url.netloc:environ["HTTP_HOST"] = request_url.netloctry:# binary_form=False gives nicer information, but wouldn't be compatible with# what Nginx or Apache could return.peer_cert = self.connection.getpeercert(binary_form=True)if peer_cert is not None:# Nginx and Apache use PEM format.environ["SSL_CLIENT_CERT"] = ssl.DER_cert_to_PEM_cert(peer_cert)except ValueError:# SSL handshake hasn't finished.self.server.log("error", "Cannot fetch SSL peer certificate info")except AttributeError:# Not using TLS, the socket will not have getpeercert().passreturn environdef run_wsgi(self):print(__name__, 'WSGIRequestHandler.run_wsgi')if self.headers.get("Expect", "").lower().strip() == "100-continue":self.wfile.write(b"HTTP/1.1 100 Continue\r\n\r\n")self.environ = environ = self.make_environ()headers_set = []headers_sent = []def write(data):assert headers_set, "write() before start_response"if not headers_sent:status, response_headers = headers_sent[:] = headers_settry:code, msg = status.split(None, 1)except ValueError:code, msg = status, ""code = int(code)self.send_response(code, msg)header_keys = set()for key, value in response_headers:self.send_header(key, value)key = key.lower()header_keys.add(key)if not ("content-length" in header_keysor environ["REQUEST_METHOD"] == "HEAD"or code < 200or code in (204, 304)):self.close_connection = Trueself.send_header("Connection", "close")if "server" not in header_keys:self.send_header("Server", self.version_string())if "date" not in header_keys:self.send_header("Date", self.date_time_string())self.end_headers()assert isinstance(data, bytes), "applications must write bytes"if data:# Only write data if there is any to avoid Python 3.5 SSL bugself.wfile.write(data)self.wfile.flush()def start_response(status, response_headers, exc_info=None):print(__name__, status, response_headers)if exc_info:try:if headers_sent:reraise(*exc_info)finally:exc_info = Noneelif headers_set:raise AssertionError("Headers already set")headers_set[:] = [status, response_headers]return writedef execute(app):application_iter = app(environ, start_response)try:for data in application_iter:write(data)if not headers_sent:write(b"")finally:if hasattr(application_iter, "close"):application_iter.close()try:execute(self.server.app)except (_ConnectionError, socket.timeout) as e:self.connection_dropped(e, environ)except Exception:if self.server.passthrough_errors:raisefrom .debug.tbtools import get_current_tracebacktraceback = get_current_traceback(ignore_system_exceptions=True)try:# if we haven't yet sent the headers but they are set# we roll back to be able to set them again.if not headers_sent:del headers_set[:]execute(InternalServerError())except Exception:passself.server.log("error", "Error on request:\n%s", traceback.plaintext)def handle(self):"""Handles a request ignoring dropped connections."""try:BaseHTTPRequestHandler.handle(self)except (_ConnectionError, socket.timeout) as e:self.connection_dropped(e)except Exception as e:if self.server.ssl_context is None or not is_ssl_error(e):raiseif self.server.shutdown_signal:self.initiate_shutdown()def initiate_shutdown(self):"""A horrible, horrible way to kill the server for Python 2.6 andlater. It's the best we can do."""# Windows does not provide SIGKILL, go with SIGTERM then.sig = getattr(signal, "SIGKILL", signal.SIGTERM)# reloader activeif is_running_from_reloader():os.kill(os.getpid(), sig)# python 2.7self.server._BaseServer__shutdown_request = True# python 2.6self.server._BaseServer__serving = Falsedef connection_dropped(self, error, environ=None):"""Called if the connection was closed by the client. By defaultnothing happens."""def handle_one_request(self):"""Handle a single HTTP request."""self.raw_requestline = self.rfile.readline()if not self.raw_requestline:self.close_connection = 1elif self.parse_request():return self.run_wsgi()def send_response(self, code, message=None):"""Send the response header and log the response code."""self.log_request(code)if message is None:message = code in self.responses and self.responses[code][0] or ""if self.request_version != "HTTP/0.9":hdr = "%s %d %s\r\n" % (self.protocol_version, code, message)self.wfile.write(hdr.encode("ascii"))def version_string(self):return BaseHTTPRequestHandler.version_string(self).strip()def address_string(self):if getattr(self, "environ", None):return self.environ["REMOTE_ADDR"]elif not self.client_address:return "<local>"elif isinstance(self.client_address, str):return self.client_addresselse:return self.client_address[0]def port_integer(self):return self.client_address[1]def log_request(self, code="-", size="-"):try:path = uri_to_iri(self.path)msg = "%s %s %s" % (self.command, path, self.request_version)except AttributeError:# path isn't set if the requestline was badmsg = self.requestlinecode = str(code)if click:color = click.styleif code[0] == "1": # 1xx - Informationalmsg = color(msg, bold=True)elif code[0] == "2": # 2xx - Successmsg = color(msg, fg="white")elif code == "304": # 304 - Resource Not Modifiedmsg = color(msg, fg="cyan")elif code[0] == "3": # 3xx - Redirectionmsg = color(msg, fg="green")elif code == "404": # 404 - Resource Not Foundmsg = color(msg, fg="yellow")elif code[0] == "4": # 4xx - Client Errormsg = color(msg, fg="red", bold=True)else: # 5xx, or any other responsemsg = color(msg, fg="magenta", bold=True)self.log("info", '"%s" %s %s', msg, code, size)def log_error(self, *args):self.log("error", *args)def log_message(self, format, *args):self.log("info", format, *args)def log(self, type, message, *args):_log(type,"%s - - [%s] %s\n"% (self.address_string(), self.log_date_time_string(), message % args),)def get_header_items(self):"""Get an iterable list of key/value pairs representing headers.This function provides Python 2/3 compatibility as related to theparsing of request headers. Python 2.7 is not compliant withRFC 3875 Section 4.1.18 which requires multiple values for headersto be provided or RFC 2616 which allows for folding of multi-lineheaders. This function will return a matching list regardlessof Python version. It can be removed once Python 2.7 supportis dropped.:return: List of tuples containing header hey/value pairs"""if PY2:# For Python 2, process the headers manually according to# W3C RFC 2616 Section 4.2.items = []for header in self.headers.headers:# Remove "\r\n" from the header and split on ":" to get# the field name and value.try:key, value = header[0:-2].split(":", 1)except ValueError:# If header could not be slit with : but starts with white# space and it follows an existing header, it's a folded# header.if header[0] in ("\t", " ") and items:# Pop off the last headerkey, value = items.pop()# Append the current header to the value of the last# header which will be placed back on the end of the# listvalue = value + header# Otherwise it's just a bad header and should errorelse:# Re-raise the value errorraise# Add the key and the value once stripped of leading# white space. The specification allows for stripping# trailing white space but the Python 3 code does not# strip trailing white space. Therefore, trailing space# will be left as is to match the Python 3 behavior.items.append((key, value.lstrip()))else:items = self.headers.items()return items#: backwards compatible name if someone is subclassing itBaseRequestHandler = WSGIRequestHandlerdef generate_adhoc_ssl_pair(cn=None):try:from cryptography import x509from cryptography.x509.oid import NameOIDfrom cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives import hashesfrom cryptography.hazmat.primitives.asymmetric import rsaexcept ImportError:raise TypeError("Using ad-hoc certificates requires the cryptography library.")pkey = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend())# pretty damn sure that this is not actually accepted by anyoneif cn is None:cn = u"*"subject = x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"Dummy Certificate"),x509.NameAttribute(NameOID.COMMON_NAME, cn),])cert = (x509.CertificateBuilder().subject_name(subject).issuer_name(subject).public_key(pkey.public_key()).serial_number(x509.random_serial_number()).not_valid_before(dt.utcnow()).not_valid_after(dt.utcnow() + timedelta(days=365)).add_extension(x509.ExtendedKeyUsage([x509.OID_SERVER_AUTH]), critical=False).add_extension(x509.SubjectAlternativeName([x509.DNSName(u"*")]), critical=False).sign(pkey, hashes.SHA256(), default_backend()))return cert, pkeydef make_ssl_devcert(base_path, host=None, cn=None):"""Creates an SSL key for development. This should be used instead ofthe ``'adhoc'`` key which generates a new cert on each server start.It accepts a path for where it should store the key and cert andeither a host or CN. If a host is given it will use the CN``*.host/CN=host``.For more information see :func:`run_simple`... versionadded:: 0.9:param base_path: the path to the certificate and key. The extension``.crt`` is added for the certificate, ``.key`` isadded for the key.:param host: the name of the host. This can be used as an alternativefor the `cn`.:param cn: the `CN` to use."""if host is not None:cn = u"*.%s/CN=%s" % (host, host)cert, pkey = generate_adhoc_ssl_pair(cn=cn)from cryptography.hazmat.primitives import serializationcert_file = base_path + ".crt"pkey_file = base_path + ".key"with open(cert_file, "wb") as f:f.write(cert.public_bytes(serialization.Encoding.PEM))with open(pkey_file, "wb") as f:f.write(pkey.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.TraditionalOpenSSL,encryption_algorithm=serialization.NoEncryption(),))return cert_file, pkey_filedef generate_adhoc_ssl_context():"""Generates an adhoc SSL context for the development server."""import tempfileimport atexitcert, pkey = generate_adhoc_ssl_pair()from cryptography.hazmat.primitives import serializationcert_handle, cert_file = tempfile.mkstemp()pkey_handle, pkey_file = tempfile.mkstemp()atexit.register(os.remove, pkey_file)atexit.register(os.remove, cert_file)os.write(cert_handle, cert.public_bytes(serialization.Encoding.PEM))os.write(pkey_handle,pkey.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.TraditionalOpenSSL,encryption_algorithm=serialization.NoEncryption(),),)os.close(cert_handle)os.close(pkey_handle)ctx = load_ssl_context(cert_file, pkey_file)return ctxdef load_ssl_context(cert_file, pkey_file=None, protocol=None):"""Loads SSL context from cert/private key files and optional protocol.Many parameters are directly taken from the API of:py:class:`ssl.SSLContext`.:param cert_file: Path of the certificate to use.:param pkey_file: Path of the private key to use. If not given, the keywill be obtained from the certificate file.:param protocol: One of the ``PROTOCOL_*`` constants in the stdlib ``ssl``module. Defaults to ``PROTOCOL_SSLv23``."""if protocol is None:try:protocol = ssl.PROTOCOL_TLS_SERVERexcept AttributeError:# Python <= 3.5 compatprotocol = ssl.PROTOCOL_SSLv23ctx = _SSLContext(protocol)ctx.load_cert_chain(cert_file, pkey_file)return ctxclass _SSLContext(object):"""A dummy class with a small subset of Python3's ``ssl.SSLContext``, onlyintended to be used with and by Werkzeug."""def __init__(self, protocol):self._protocol = protocolself._certfile = Noneself._keyfile = Noneself._password = Nonedef load_cert_chain(self, certfile, keyfile=None, password=None):self._certfile = certfileself._keyfile = keyfile or certfileself._password = passworddef wrap_socket(self, sock, **kwargs):return ssl.wrap_socket(sock,keyfile=self._keyfile,certfile=self._certfile,ssl_version=self._protocol,**kwargs)def is_ssl_error(error=None):"""Checks if the given error (or the current one) is an SSL error."""if error is None:error = sys.exc_info()[1]return isinstance(error, ssl.SSLError)def select_address_family(host, port):"""Return ``AF_INET4``, ``AF_INET6``, or ``AF_UNIX`` depending onthe host and port."""# disabled due to problems with current ipv6 implementations# and various operating systems. Probably this code also is# not supposed to work, but I can't come up with any other# ways to implement this.# try:# info = socket.getaddrinfo(host, port, socket.AF_UNSPEC,# socket.SOCK_STREAM, 0,# socket.AI_PASSIVE)# if info:# return info[0][0]# except socket.gaierror:# passif host.startswith("unix://"):return socket.AF_UNIXelif ":" in host and hasattr(socket, "AF_INET6"):return socket.AF_INET6return socket.AF_INETdef get_sockaddr(host, port, family):"""Return a fully qualified socket address that can be passed to:func:`socket.bind`."""if family == af_unix:return host.split("://", 1)[1]try:res = socket.getaddrinfo(host, port, family, socket.SOCK_STREAM, socket.IPPROTO_TCP)except socket.gaierror:return host, portreturn res[0][4]class BaseWSGIServer(HTTPServer, object):"""Simple single-threaded, single-process WSGI server."""multithread = Falsemultiprocess = Falserequest_queue_size = LISTEN_QUEUEdef __init__(self,host,port,app,handler=None,passthrough_errors=False,ssl_context=None,fd=None,):if handler is None:handler = WSGIRequestHandlerself.address_family = select_address_family(host, port)if fd is not None:real_sock = socket.fromfd(fd, self.address_family, socket.SOCK_STREAM)port = 0server_address = get_sockaddr(host, int(port), self.address_family)# remove socket file if it already existsif self.address_family == af_unix and os.path.exists(server_address):os.unlink(server_address)HTTPServer.__init__(self, server_address, handler)self.app = appself.passthrough_errors = passthrough_errorsself.shutdown_signal = Falseself.host = hostself.port = self.socket.getsockname()[1]# Patch in the original socket.if fd is not None:self.socket.close()self.socket = real_sockself.server_address = self.socket.getsockname()if ssl_context is not None:if isinstance(ssl_context, tuple):ssl_context = load_ssl_context(*ssl_context)if ssl_context == "adhoc":ssl_context = generate_adhoc_ssl_context()# If we are on Python 2 the return value from socket.fromfd# is an internal socket object but what we need for ssl wrap# is the wrapper around it :(sock = self.socketif PY2 and not isinstance(sock, socket.socket):sock = socket.socket(sock.family, sock.type, sock.proto, sock)self.socket = ssl_context.wrap_socket(sock, server_side=True)self.ssl_context = ssl_contextelse:self.ssl_context = Nonedef log(self, type, message, *args):_log(type, message, *args)def serve_forever(self):self.shutdown_signal = Falsetry:HTTPServer.serve_forever(self)except KeyboardInterrupt:passfinally:self.server_close()def handle_error(self, request, client_address):if self.passthrough_errors:raise# Python 2 still causes a socket.error after the earlier# handling, so silence it here.if isinstance(sys.exc_info()[1], _ConnectionError):returnreturn HTTPServer.handle_error(self, request, client_address)def get_request(self):con, info = self.socket.accept()return con, infoclass ThreadedWSGIServer(ThreadingMixIn, BaseWSGIServer):"""A WSGI server that does threading."""multithread = Truedaemon_threads = Trueclass ForkingWSGIServer(ForkingMixIn, BaseWSGIServer):"""A WSGI server that does forking."""multiprocess = Truedef __init__(self,host,port,app,processes=40,handler=None,passthrough_errors=False,ssl_context=None,fd=None,):if not can_fork:raise ValueError("Your platform does not support forking.")BaseWSGIServer.__init__(self, host, port, app, handler, passthrough_errors, ssl_context, fd)self.max_children = processesdef make_server(host=None,port=None,app=None,threaded=False,processes=1,request_handler=None,passthrough_errors=False,ssl_context=None,fd=None,):"""Create a new server instance that is either threaded, or forksor just processes one request after another."""if threaded and processes > 1:raise ValueError("cannot have a multithreaded and multi process server.")elif threaded:return ThreadedWSGIServer(host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd)elif processes > 1:return ForkingWSGIServer(host,port,app,processes,request_handler,passthrough_errors,ssl_context,fd=fd,)else:return BaseWSGIServer(host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd)def is_running_from_reloader():"""Checks if the application is running from within the Werkzeugreloader subprocess... versionadded:: 0.10"""return os.environ.get("WERKZEUG_RUN_MAIN") == "true"def run_simple(hostname,port,application,use_reloader=False,use_debugger=False,use_evalex=True,extra_files=None,reloader_interval=1,reloader_type="auto",threaded=False,processes=1,request_handler=None,static_files=None,passthrough_errors=False,ssl_context=None,):"""Start a WSGI application. Optional features include a reloader,multithreading and fork support.This function has a command-line interface too::python -m werkzeug.serving --help.. versionadded:: 0.5`static_files` was added to simplify serving of static files as wellas `passthrough_errors`... versionadded:: 0.6support for SSL was added... versionadded:: 0.8Added support for automatically loading a SSL context from certificatefile and private key... versionadded:: 0.9Added command-line interface... versionadded:: 0.10Improved the reloader and added support for changing the backendthrough the `reloader_type` parameter. See :ref:`reloader`for more information... versionchanged:: 0.15Bind to a Unix socket by passing a path that starts with``unix://`` as the ``hostname``.:param hostname: The host to bind to, for example ``'localhost'``.If the value is a path that starts with ``unix://`` it will bindto a Unix socket instead of a TCP socket..:param port: The port for the server. eg: ``8080``:param application: the WSGI application to execute:param use_reloader: should the server automatically restart the pythonprocess if modules were changed?:param use_debugger: should the werkzeug debugging system be used?:param use_evalex: should the exception evaluation feature be enabled?:param extra_files: a list of files the reloader should watchadditionally to the modules. For example configurationfiles.:param reloader_interval: the interval for the reloader in seconds.:param reloader_type: the type of reloader to use. The default isauto detection. Valid values are ``'stat'`` and``'watchdog'``. See :ref:`reloader` for moreinformation.:param threaded: should the process handle each request in a separatethread?:param processes: if greater than 1 then handle each request in a new processup to this maximum number of concurrent processes.:param request_handler: optional parameter that can be used to replacethe default one. You can use this to replace itwith a different:class:`~BaseHTTPServer.BaseHTTPRequestHandler`subclass.:param static_files: a list or dict of paths for static files. This worksexactly like :class:`SharedDataMiddleware`, it's actuallyjust wrapping the application in that middleware beforeserving.:param passthrough_errors: set this to `True` to disable the error catching.This means that the server will die on errors butit can be useful to hook debuggers in (pdb etc.):param ssl_context: an SSL context for the connection. Either an:class:`ssl.SSLContext`, a tuple in the form``(cert_file, pkey_file)``, the string ``'adhoc'`` ifthe server should automatically create one, or ``None``to disable SSL (which is the default)."""if not isinstance(port, int):raise TypeError("port must be an integer")if use_debugger:from .debug import DebuggedApplicationapplication = DebuggedApplication(application, use_evalex)if static_files:from .middleware.shared_data import SharedDataMiddlewareapplication = SharedDataMiddleware(application, static_files)def log_startup(sock):display_hostname = hostname if hostname not in ("", "*") else "localhost"quit_msg = "(Press CTRL+C to quit)"if sock.family == af_unix:_log("info", " * Running on %s %s", display_hostname, quit_msg)else:if ":" in display_hostname:display_hostname = "[%s]" % display_hostnameport = sock.getsockname()[1]_log("info"," * Running on %s://%s:%d/ %s","http" if ssl_context is None else "https",display_hostname,port,quit_msg,)def inner():try:fd = int(os.environ["WERKZEUG_SERVER_FD"])except (LookupError, ValueError):fd = Nonesrv = make_server(hostname,port,application,threaded,processes,request_handler,passthrough_errors,ssl_context,fd=fd,)if fd is None:log_startup(srv.socket)srv.serve_forever()if use_reloader:# If we're not running already in the subprocess that is the# reloader we want to open up a socket early to make sure the# port is actually available.if not is_running_from_reloader():if port == 0 and not can_open_by_fd:raise ValueError("Cannot bind to a random port with enabled ""reloader if the Python interpreter does ""not support socket opening by fd.")# Create and destroy a socket so that any exceptions are# raised before we spawn a separate Python interpreter and# lose this ability.address_family = select_address_family(hostname, port)server_address = get_sockaddr(hostname, port, address_family)s = socket.socket(address_family, socket.SOCK_STREAM)s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)s.bind(server_address)if hasattr(s, "set_inheritable"):s.set_inheritable(True)# If we can open the socket by file descriptor, then we can just# reuse this one and our socket will survive the restarts.if can_open_by_fd:os.environ["WERKZEUG_SERVER_FD"] = str(s.fileno())s.listen(LISTEN_QUEUE)log_startup(s)else:s.close()if address_family == af_unix:_log("info", "Unlinking %s" % server_address)os.unlink(server_address)# Do not use relative imports, otherwise "python -m werkzeug.serving"# breaks.from ._reloader import run_with_reloaderrun_with_reloader(inner, extra_files, reloader_interval, reloader_type)else:inner()def run_with_reloader(*args, **kwargs):# People keep using undocumented APIs. Do not use this function# please, we do not guarantee that it continues working.from ._reloader import run_with_reloaderreturn run_with_reloader(*args, **kwargs)def main():"""A simple command-line interface for :py:func:`run_simple`."""# in contrast to argparse, this works at least under Python < 2.7import optparsefrom .utils import import_stringparser = optparse.OptionParser(usage="Usage: %prog [options] app_module:app_object")parser.add_option("-b","--bind",dest="address",help="The hostname:port the app should listen on.",)parser.add_option("-d","--debug",dest="use_debugger",action="store_true",default=False,help="Use Werkzeug's debugger.",)parser.add_option("-r","--reload",dest="use_reloader",action="store_true",default=False,help="Reload Python process if modules change.",)options, args = parser.parse_args()hostname, port = None, Noneif options.address:address = options.address.split(":")hostname = address[0]if len(address) > 1:port = address[1]if len(args) != 1:sys.stdout.write("No application supplied, or too much. See --help\n")sys.exit(1)app = import_string(args[0])run_simple(hostname=(hostname or "127.0.0.1"),port=int(port or 5000),application=app,use_reloader=options.use_reloader,use_debugger=options.use_debugger,)if __name__ == "__main__":main()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。