diff --git a/docs/deployment.md b/docs/deployment.md index 2224f98f4..f1895bcfa 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -86,7 +86,7 @@ Options: Enable/Disable default Server header. --date-header / --no-date-header Enable/Disable default Date header. - --forwarded-allow-ips TEXT Comma seperated list of IPs to trust with + --forwarded-allow-ips TEXT Comma separated list of IPs to trust with proxy headers. Defaults to the $FORWARDED_ALLOW_IPS environment variable if available, or '127.0.0.1'. diff --git a/docs/index.md b/docs/index.md index 97726a5ae..2befd121a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -155,7 +155,7 @@ Options: Enable/Disable default Server header. --date-header / --no-date-header Enable/Disable default Date header. - --forwarded-allow-ips TEXT Comma seperated list of IPs to trust with + --forwarded-allow-ips TEXT Comma separated list of IPs to trust with proxy headers. Defaults to the $FORWARDED_ALLOW_IPS environment variable if available, or '127.0.0.1'. diff --git a/uvicorn/main.py b/uvicorn/main.py index 0db1216c5..aeeae7d93 100644 --- a/uvicorn/main.py +++ b/uvicorn/main.py @@ -19,6 +19,11 @@ SSL_PROTOCOL_VERSION, WS_PROTOCOLS, Config, + HTTPProtocolType, + InterfaceType, + LifespanType, + LoopSetupType, + WSProtocolType, ) from uvicorn.server import Server, ServerState # noqa: F401 # Used to be defined here. from uvicorn.supervisors import ChangeReload, Multiprocess @@ -233,7 +238,7 @@ def print_version(ctx: click.Context, param: click.Parameter, value: bool) -> No "--forwarded-allow-ips", type=str, default=None, - help="Comma seperated list of IPs to trust with proxy headers. Defaults to" + help="Comma separated list of IPs to trust with proxy headers. Defaults to" " the $FORWARDED_ALLOW_IPS environment variable if available, or '127.0.0.1'.", ) @click.option( @@ -347,15 +352,15 @@ def main( port: int, uds: str, fd: int, - loop: str, - http: str, - ws: str, + loop: LoopSetupType, + http: HTTPProtocolType, + ws: WSProtocolType, ws_max_size: int, ws_ping_interval: float, ws_ping_timeout: float, ws_per_message_deflate: bool, - lifespan: str, - interface: str, + lifespan: LifespanType, + interface: InterfaceType, debug: bool, reload: bool, reload_dirs: typing.List[str], @@ -388,53 +393,162 @@ def main( app_dir: str, factory: bool, ) -> None: - kwargs = { - "host": host, - "port": port, - "uds": uds, - "fd": fd, - "loop": loop, - "http": http, - "ws": ws, - "ws_max_size": ws_max_size, - "ws_ping_interval": ws_ping_interval, - "ws_ping_timeout": ws_ping_timeout, - "ws_per_message_deflate": ws_per_message_deflate, - "lifespan": lifespan, - "env_file": env_file, - "log_config": LOGGING_CONFIG if log_config is None else log_config, - "log_level": log_level, - "access_log": access_log, - "interface": interface, - "debug": debug, - "reload": reload, - "reload_dirs": reload_dirs if reload_dirs else None, - "reload_includes": reload_includes if reload_includes else None, - "reload_excludes": reload_excludes if reload_excludes else None, - "reload_delay": reload_delay, - "workers": workers, - "proxy_headers": proxy_headers, - "server_header": server_header, - "date_header": date_header, - "forwarded_allow_ips": forwarded_allow_ips, - "root_path": root_path, - "limit_concurrency": limit_concurrency, - "backlog": backlog, - "limit_max_requests": limit_max_requests, - "timeout_keep_alive": timeout_keep_alive, - "ssl_keyfile": ssl_keyfile, - "ssl_certfile": ssl_certfile, - "ssl_keyfile_password": ssl_keyfile_password, - "ssl_version": ssl_version, - "ssl_cert_reqs": ssl_cert_reqs, - "ssl_ca_certs": ssl_ca_certs, - "ssl_ciphers": ssl_ciphers, - "headers": [header.split(":", 1) for header in headers], - "use_colors": use_colors, - "factory": factory, - "app_dir": app_dir, - } - run(app, **kwargs) + run( + app, + host=host, + port=port, + uds=uds, + fd=fd, + loop=loop, + http=http, + ws=ws, + ws_max_size=ws_max_size, + ws_ping_interval=ws_ping_interval, + ws_ping_timeout=ws_ping_timeout, + ws_per_message_deflate=ws_per_message_deflate, + lifespan=lifespan, + env_file=env_file, + log_config=LOGGING_CONFIG if log_config is None else log_config, + log_level=log_level, + access_log=access_log, + interface=interface, + debug=debug, + reload=reload, + reload_dirs=reload_dirs if reload_dirs else None, + reload_includes=reload_includes if reload_includes else None, + reload_excludes=reload_excludes if reload_excludes else None, + reload_delay=reload_delay, + workers=workers, + proxy_headers=proxy_headers, + server_header=server_header, + date_header=date_header, + forwarded_allow_ips=forwarded_allow_ips, + root_path=root_path, + limit_concurrency=limit_concurrency, + backlog=backlog, + limit_max_requests=limit_max_requests, + timeout_keep_alive=timeout_keep_alive, + ssl_keyfile=ssl_keyfile, + ssl_certfile=ssl_certfile, + ssl_keyfile_password=ssl_keyfile_password, + ssl_version=ssl_version, + ssl_cert_reqs=ssl_cert_reqs, + ssl_ca_certs=ssl_ca_certs, + ssl_ciphers=ssl_ciphers, + headers=[header.split(":", 1) for header in headers], + use_colors=use_colors, + factory=factory, + app_dir=app_dir, + ) + + +@typing.overload # type: ignore[misc] +def run( + app: typing.Union[ASGIApplication, str], + *, + host: str, + port: int, + uds: str, + fd: int, + loop: LoopSetupType, + http: HTTPProtocolType, + ws: WSProtocolType, + ws_max_size: int, + ws_ping_interval: float, + ws_ping_timeout: float, + ws_per_message_deflate: bool, + lifespan: LifespanType, + interface: InterfaceType, + debug: bool, + reload: bool, + reload_dirs: typing.Optional[typing.List[str]], + reload_includes: typing.Optional[typing.List[str]], + reload_excludes: typing.Optional[typing.List[str]], + reload_delay: float, + workers: int, + env_file: str, + log_config: str, + log_level: str, + access_log: bool, + proxy_headers: bool, + server_header: bool, + date_header: bool, + forwarded_allow_ips: str, + root_path: str, + limit_concurrency: int, + backlog: int, + limit_max_requests: int, + timeout_keep_alive: int, + ssl_keyfile: str, + ssl_certfile: str, + ssl_keyfile_password: str, + ssl_version: int, + ssl_cert_reqs: int, + ssl_ca_certs: str, + ssl_ciphers: str, + headers: typing.Sequence[typing.Sequence[str]], + use_colors: bool, + app_dir: str, + factory: bool, +) -> None: + """Run uvicorn via Python code. + + Args: + app (typing.Union[ASGIApplication, str]): ASGI application itself or path to it. + Use the latter with `--reload`. + host (str): Hostname to listen on. + port (int): Port to listen on. + uds (str): Path to a Unix domain socket to listen on. + fd (int): File descriptor number to listen on. + loop (Literal["auto", "uvloop", "asyncio"]): Event loop implementation. + http (Literal["auto", "h11", "httptools"]): HTTP implementation. + ws (Literal["auto", "none", "websockets", "wsproto"]): WebSocket + implementation. + ws_max_size (int): Maximum message size. + ws_ping_interval (float): Websocket ping interval. + ws_ping_timeout (float): Websocket ping timeout. + ws_per_message_deflate (bool): Enable per-message deflate. + lifespan (Literal["auto", "on", "off"]): Lifespan of the application. + interface (Literal["auto", "asgi3", "asgi2", "wsgi"]): Application interface. + debug (bool): Turn on debug mode. + reload (bool): Turn on auto reload. + reload_dirs (typing.List[str]): Directories to watch for changes. + reload_includes (typing.List[str]): Filename patterns to include. + reload_excludes (typing.List[str]): Filename patterns to exclude. + reload_delay (float): Delay to watch for changes. + workers (int): Number of workers. + env_file (str): Path to a file to load environment variables from. + log_config (str): Path to a file to load logging configuration from. + log_level (str): Logging level. + access_log (bool): Turn on access log. + proxy_headers (bool): Turn on proxy headers support. + server_header (bool): Turn on server header support. + date_header (bool): Turn on date header support. + forwarded_allow_ips (str): Comma separated list of IPs to trust with proxy + headers. + root_path (str): Set the ASGI 'root_path' for applications submounted below a + given URL path. + limit_concurrency (int): Maximum number of concurrent connections or tasks to + allow, before issuing HTTP 503 responses. + backlog (int): Maximum number of connections to hold in backlog. + limit_max_requests (int): Maximum number of requests to service before + terminating the process. + timeout_keep_alive (int): Timeout for keep-alive connections. + ssl_keyfile (str): Path to a file containing the SSL key. + ssl_certfile (str): Path to a file containing the SSL certificate. + ssl_keyfile_password (str): Password to unlock the SSL key. + ssl_version (int): SSL version to use. + ssl_cert_reqs (int): SSL certificate requirements. + ssl_ca_certs (str): Path to a file containing the SSL certificate authority. + ssl_ciphers (str): SSL ciphers to use. + headers (typing.Sequence[typing.Sequence[str]]): Custom default HTTP response + headers. + use_colors (bool): Turn on colorized logging. + app_dir (str): Look for APP in the specified directory, by adding this to the + PYTHONPATH. + factory (bool): Use the ASGI factory mode. + """ + ... def run(app: typing.Union[ASGIApplication, str], **kwargs: typing.Any) -> None: