mirror of
https://github.com/django/daphne.git
synced 2025-04-16 06:42:02 +03:00
219 lines
7.2 KiB
Python
Executable File
219 lines
7.2 KiB
Python
Executable File
import argparse
|
|
import logging
|
|
import sys
|
|
|
|
from .access import AccessLogGenerator
|
|
from .endpoints import build_endpoint_description_strings
|
|
from .server import Server
|
|
from .utils import import_by_path
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
DEFAULT_HOST = "127.0.0.1"
|
|
DEFAULT_PORT = 8000
|
|
|
|
|
|
class CommandLineInterface(object):
|
|
"""
|
|
Acts as the main CLI entry point for running the server.
|
|
"""
|
|
|
|
description = "Django HTTP/WebSocket server"
|
|
|
|
server_class = Server
|
|
|
|
def __init__(self):
|
|
self.parser = argparse.ArgumentParser(
|
|
description=self.description,
|
|
)
|
|
self.parser.add_argument(
|
|
"-p",
|
|
"--port",
|
|
type=int,
|
|
help="Port number to listen on",
|
|
default=None,
|
|
)
|
|
self.parser.add_argument(
|
|
"-b",
|
|
"--bind",
|
|
dest="host",
|
|
help="The host/address to bind to",
|
|
default=None,
|
|
)
|
|
self.parser.add_argument(
|
|
"--websocket_timeout",
|
|
type=int,
|
|
help="Maximum time to allow a websocket to be connected. -1 for infinite.",
|
|
default=86400,
|
|
)
|
|
self.parser.add_argument(
|
|
"--websocket_connect_timeout",
|
|
type=int,
|
|
help="Maximum time to allow a connection to handshake. -1 for infinite",
|
|
default=5,
|
|
)
|
|
self.parser.add_argument(
|
|
"-u",
|
|
"--unix-socket",
|
|
dest="unix_socket",
|
|
help="Bind to a UNIX socket rather than a TCP host/port",
|
|
default=None,
|
|
)
|
|
self.parser.add_argument(
|
|
"--fd",
|
|
type=int,
|
|
dest="file_descriptor",
|
|
help="Bind to a file descriptor rather than a TCP host/port or named unix socket",
|
|
default=None,
|
|
)
|
|
self.parser.add_argument(
|
|
"-e",
|
|
"--endpoint",
|
|
dest="socket_strings",
|
|
action="append",
|
|
help="Use raw server strings passed directly to twisted",
|
|
default=[],
|
|
)
|
|
self.parser.add_argument(
|
|
"-v",
|
|
"--verbosity",
|
|
type=int,
|
|
help="How verbose to make the output",
|
|
default=1,
|
|
)
|
|
self.parser.add_argument(
|
|
"-t",
|
|
"--http-timeout",
|
|
type=int,
|
|
help="How long to wait for worker before timing out HTTP connections",
|
|
default=120,
|
|
)
|
|
self.parser.add_argument(
|
|
"--access-log",
|
|
help="Where to write the access log (- for stdout, the default for verbosity=1)",
|
|
default=None,
|
|
)
|
|
self.parser.add_argument(
|
|
"--ping-interval",
|
|
type=int,
|
|
help="The number of seconds a WebSocket must be idle before a keepalive ping is sent",
|
|
default=20,
|
|
)
|
|
self.parser.add_argument(
|
|
"--ping-timeout",
|
|
type=int,
|
|
help="The number of seconds before a WebSocket is closed if no response to a keepalive ping",
|
|
default=30,
|
|
)
|
|
self.parser.add_argument(
|
|
"--application-close-timeout",
|
|
type=int,
|
|
help="The number of seconds an ASGI application has to exit after client disconnect before it is killed",
|
|
default=10,
|
|
)
|
|
self.parser.add_argument(
|
|
"--ws-protocol",
|
|
nargs="*",
|
|
dest="ws_protocols",
|
|
help="The WebSocket protocols you wish to support",
|
|
default=None,
|
|
)
|
|
self.parser.add_argument(
|
|
"--root-path",
|
|
dest="root_path",
|
|
help="The setting for the ASGI root_path variable",
|
|
default="",
|
|
)
|
|
self.parser.add_argument(
|
|
"--proxy-headers",
|
|
dest="proxy_headers",
|
|
help="Enable parsing and using of X-Forwarded-For and X-Forwarded-Port headers and using that as the "
|
|
"client address",
|
|
default=False,
|
|
action="store_true",
|
|
)
|
|
self.parser.add_argument(
|
|
"application",
|
|
help="The application to dispatch to as path.to.module:instance.path",
|
|
)
|
|
|
|
self.server = None
|
|
|
|
@classmethod
|
|
def entrypoint(cls):
|
|
"""
|
|
Main entrypoint for external starts.
|
|
"""
|
|
cls().run(sys.argv[1:])
|
|
|
|
def run(self, args):
|
|
"""
|
|
Pass in raw argument list and it will decode them
|
|
and run the server.
|
|
"""
|
|
# Decode args
|
|
args = self.parser.parse_args(args)
|
|
# Set up logging
|
|
logging.basicConfig(
|
|
level={
|
|
0: logging.WARN,
|
|
1: logging.INFO,
|
|
2: logging.DEBUG,
|
|
3: logging.DEBUG, # Also turns on asyncio debug
|
|
}[args.verbosity],
|
|
format="%(asctime)-15s %(levelname)-8s %(message)s",
|
|
)
|
|
# If verbosity is 1 or greater, or they told us explicitly, set up access log
|
|
access_log_stream = None
|
|
if args.access_log:
|
|
if args.access_log == "-":
|
|
access_log_stream = sys.stdout
|
|
else:
|
|
access_log_stream = open(args.access_log, "a", 1)
|
|
elif args.verbosity >= 1:
|
|
access_log_stream = sys.stdout
|
|
# Import application
|
|
sys.path.insert(0, ".")
|
|
application = import_by_path(args.application)
|
|
# Set up port/host bindings
|
|
if not any([args.host, args.port is not None, args.unix_socket, args.file_descriptor, args.socket_strings]):
|
|
# no advanced binding options passed, patch in defaults
|
|
args.host = DEFAULT_HOST
|
|
args.port = DEFAULT_PORT
|
|
elif args.host and args.port is None:
|
|
args.port = DEFAULT_PORT
|
|
elif args.port is not None and not args.host:
|
|
args.host = DEFAULT_HOST
|
|
# Build endpoint description strings from (optional) cli arguments
|
|
endpoints = build_endpoint_description_strings(
|
|
host=args.host,
|
|
port=args.port,
|
|
unix_socket=args.unix_socket,
|
|
file_descriptor=args.file_descriptor
|
|
)
|
|
endpoints = sorted(
|
|
args.socket_strings + endpoints
|
|
)
|
|
# Start the server
|
|
logger.info(
|
|
"Starting server at %s" %
|
|
(", ".join(endpoints), )
|
|
)
|
|
self.server = self.server_class(
|
|
application=application,
|
|
endpoints=endpoints,
|
|
http_timeout=args.http_timeout,
|
|
ping_interval=args.ping_interval,
|
|
ping_timeout=args.ping_timeout,
|
|
websocket_timeout=args.websocket_timeout,
|
|
websocket_connect_timeout=args.websocket_connect_timeout,
|
|
application_close_timeout=args.application_close_timeout,
|
|
action_logger=AccessLogGenerator(access_log_stream) if access_log_stream else None,
|
|
ws_protocols=args.ws_protocols,
|
|
root_path=args.root_path,
|
|
verbosity=args.verbosity,
|
|
proxy_forwarded_address_header="X-Forwarded-For" if args.proxy_headers else None,
|
|
proxy_forwarded_port_header="X-Forwarded-Port" if args.proxy_headers else None,
|
|
)
|
|
self.server.run()
|