def test_message_logger(caplog): def app(scope): async def asgi(receive, send): message = await receive() await send({ "type": "http.response.start", "status": 200, "headers": [] }) await send({ "type": "http.response.body", "body": b"", "more_body": False }) return asgi caplog.set_level(logging.DEBUG, logger="uvicorn") app = MessageLoggerMiddleware(app) client = TestClient(app) response = client.get("/") assert response.status_code == 200 messages = [record.msg % record.args for record in caplog.records] assert sum(['ASGI [1] Initialized' in message for message in messages]) == 1 assert sum(['ASGI [1] Started task' in message for message in messages]) == 1 assert sum(['ASGI [1] Sent' in message for message in messages]) == 1 assert sum(['ASGI [1] Received' in message for message in messages]) == 2 assert sum(['ASGI [1] Completed' in message for message in messages]) == 1 assert sum( ['ASGI [1] Raised exception' in message for message in messages]) == 0
def load(self): assert not self.loaded if isinstance(self.http, str): self.http_protocol_class = import_from_string( HTTP_PROTOCOLS[self.http]) else: self.http_protocol_class = self.http if isinstance(self.ws, str): self.ws_protocol_class = import_from_string(WS_PROTOCOLS[self.ws]) else: self.ws_protocol_class = self.ws self.lifespan_class = import_from_string(LIFESPAN[self.lifespan]) try: self.loaded_app = import_from_string(self.app) except ImportFromStringError as exc: self.logger_instance.error("Error loading ASGI app. %s" % exc) sys.exit(1) if self.wsgi: self.loaded_app = WSGIMiddleware(self.loaded_app) self.ws_protocol_class = None if self.debug: self.loaded_app = DebugMiddleware(self.loaded_app) if self.logger_instance.level <= logging.DEBUG: self.loaded_app = MessageLoggerMiddleware(self.loaded_app) if self.proxy_headers: self.loaded_app = ProxyHeadersMiddleware(self.loaded_app) self.loaded = True
async def test_message_logger(caplog): async def app(scope, receive, send): await receive() await send({ "type": "http.response.start", "status": 200, "headers": [] }) await send({ "type": "http.response.body", "body": b"", "more_body": False }) with caplog_for_logger(caplog, "uvicorn.asgi"): caplog.set_level(TRACE_LOG_LEVEL, logger="uvicorn.asgi") caplog.set_level(TRACE_LOG_LEVEL) app = MessageLoggerMiddleware(app) async with httpx.AsyncClient(app=app, base_url="http://testserver") as client: response = await client.get("/") assert response.status_code == 200 messages = [record.msg % record.args for record in caplog.records] assert sum(["ASGI [1] Started" in message for message in messages]) == 1 assert sum(["ASGI [1] Send" in message for message in messages]) == 2 assert sum(["ASGI [1] Receive" in message for message in messages]) == 1 assert sum(["ASGI [1] Completed" in message for message in messages]) == 1 assert (sum([ "ASGI [1] Raised exception" in message for message in messages ]) == 0)
def test_message_logger(caplog): async def app(scope, receive, send): message = await receive() await send({ "type": "http.response.start", "status": 200, "headers": [] }) await send({ "type": "http.response.body", "body": b"", "more_body": False }) caplog.set_level(TRACE_LOG_LEVEL, logger="uvicorn.asgi") caplog.set_level(TRACE_LOG_LEVEL) app = MessageLoggerMiddleware(app) client = TestClient(app) response = client.get("/") assert response.status_code == 200 messages = [record.msg % record.args for record in caplog.records] assert sum("ASGI [1] Started" in message for message in messages) == 1 assert sum("ASGI [1] Send" in message for message in messages) == 2 assert sum("ASGI [1] Receive" in message for message in messages) == 1 assert sum("ASGI [1] Completed" in message for message in messages) == 1 assert sum("ASGI [1] Raised exception" in message for message in messages) == 0
def load(self): assert not self.loaded encoded_headers = [ (key.lower().encode("latin1"), value.encode("latin1")) for key, value in self.headers ] self.encoded_headers = ( encoded_headers if b"server" in dict(encoded_headers) else [(b"server", b"uvicorn")] + encoded_headers ) # type: List[Tuple[bytes, bytes]] if isinstance(self.http, str): self.http_protocol_class = import_from_string(HTTP_PROTOCOLS[self.http]) else: self.http_protocol_class = self.http if isinstance(self.ws, str): self.ws_protocol_class = import_from_string(WS_PROTOCOLS[self.ws]) else: self.ws_protocol_class = self.ws self.lifespan_class = import_from_string(LIFESPAN[self.lifespan]) try: self.loaded_app = import_from_string(self.app) except ImportFromStringError as exc: self.logger_instance.error("Error loading ASGI app. %s" % exc) sys.exit(1) if self.interface == "auto": if inspect.isclass(self.loaded_app): use_asgi_3 = hasattr(self.loaded_app, "__await__") elif inspect.isfunction(self.loaded_app): use_asgi_3 = asyncio.iscoroutinefunction(self.loaded_app) else: call = getattr(self.loaded_app, "__call__", None) use_asgi_3 = asyncio.iscoroutinefunction(call) self.interface = "asgi3" if use_asgi_3 else "asgi2" if self.interface == "wsgi": self.loaded_app = WSGIMiddleware(self.loaded_app) self.ws_protocol_class = None elif self.interface == "asgi2": self.loaded_app = ASGI2Middleware(self.loaded_app) if self.debug: self.loaded_app = DebugMiddleware(self.loaded_app) if self.logger_instance.level <= logging.DEBUG: self.loaded_app = MessageLoggerMiddleware(self.loaded_app) if self.proxy_headers: self.loaded_app = ProxyHeadersMiddleware(self.loaded_app) self.loaded = True
def load(self): assert not self.loaded if self.logger is None: self.logger_instance = get_logger(self.log_level) else: self.logger_instance = self.logger if isinstance(self.http, str): self.http_protocol_class = import_from_string(HTTP_PROTOCOLS[self.http]) else: self.http_protocol_class = self.http if isinstance(self.ws, str): self.ws_protocol_class = import_from_string(WS_PROTOCOLS[self.ws]) else: self.ws_protocol_class = self.ws self.lifespan_class = import_from_string(LIFESPAN[self.lifespan]) try: self.loaded_app = import_from_string(self.app) except ImportFromStringError as exc: self.logger_instance.error("Error loading ASGI app. %s" % exc) sys.exit(1) if self.wsgi: self.loaded_app = WSGIMiddleware(self.loaded_app) self.ws_protocol_class = None if self.debug: self.loaded_app = DebugMiddleware(self.loaded_app) if self.logger_instance.level <= logging.DEBUG: self.loaded_app = MessageLoggerMiddleware(self.loaded_app) if self.proxy_headers: self.loaded_app = ProxyHeadersMiddleware(self.loaded_app) if self.ssl_keyfile or self.ssl_certfile: self.ssl = create_ssl_context( keyfile=self.ssl_keyfile, certfile=self.ssl_certfile, ssl_version=self.ssl_version, cert_reqs=self.ssl_cert_reqs, ca_certs=self.ssl_ca_certs, ciphers=self.ssl_ciphers, ) else: self.ssl = None self.loaded = True
def test_message_logger_exc(caplog): async def app(scope, receive, send): raise RuntimeError() caplog.set_level(logging.DEBUG, logger="uvicorn") app = MessageLoggerMiddleware(app) client = TestClient(app) with pytest.raises(RuntimeError): client.get("/") messages = [record.msg % record.args for record in caplog.records] assert sum(["ASGI [1] Started" in message for message in messages]) == 1 assert sum(["ASGI [1] Sent" in message for message in messages]) == 0 assert sum(["ASGI [1] Received" in message for message in messages]) == 0 assert sum(["ASGI [1] Completed" in message for message in messages]) == 0 assert sum(["ASGI [1] Raised exception" in message for message in messages]) == 1
def load(self): assert not self.loaded if isinstance(self.http, str): self.http_protocol_class = import_from_string( HTTP_PROTOCOLS[self.http]) else: self.http_protocol_class = self.http if isinstance(self.ws, str): self.ws_protocol_class = import_from_string(WS_PROTOCOLS[self.ws]) else: self.ws_protocol_class = self.ws self.lifespan_class = import_from_string(LIFESPAN[self.lifespan]) try: self.loaded_app = import_from_string(self.app) except ImportFromStringError as exc: self.logger_instance.error("Error loading ASGI app. %s" % exc) sys.exit(1) if self.interface == "auto": if inspect.isclass(self.loaded_app): use_asgi_3 = hasattr(self.loaded_app, "__await__") elif inspect.isfunction(self.loaded_app): use_asgi_3 = asyncio.iscoroutinefunction(self.loaded_app) else: call = getattr(self.loaded_app, "__call__", None) use_asgi_3 = asyncio.iscoroutinefunction(call) self.interface = "asgi3" if use_asgi_3 else "asgi2" if self.interface == "wsgi": self.loaded_app = WSGIMiddleware(self.loaded_app) self.ws_protocol_class = None elif self.interface == "asgi3": self.loaded_app = ASGI3Middleware(self.loaded_app) if self.debug: self.loaded_app = DebugMiddleware(self.loaded_app) if self.logger_instance.level <= logging.DEBUG: self.loaded_app = MessageLoggerMiddleware(self.loaded_app) if self.proxy_headers: self.loaded_app = ProxyHeadersMiddleware(self.loaded_app) self.loaded = True
async def test_message_logger_exc(caplog): async def app(scope, receive, send): raise RuntimeError() caplog.set_level(TRACE_LOG_LEVEL, logger="uvicorn.asgi") caplog.set_level(TRACE_LOG_LEVEL) app = MessageLoggerMiddleware(app) async with httpx.AsyncClient(app=app, base_url="http://testserver") as client: with pytest.raises(RuntimeError): await client.get("/") messages = [record.msg % record.args for record in caplog.records] assert sum(["ASGI [1] Started" in message for message in messages]) == 1 assert sum(["ASGI [1] Send" in message for message in messages]) == 0 assert sum(["ASGI [1] Receive" in message for message in messages]) == 0 assert sum(["ASGI [1] Completed" in message for message in messages]) == 0 assert sum( ["ASGI [1] Raised exception" in message for message in messages]) == 1
def test_message_logger_scope_exc(caplog): def app(scope): raise RuntimeError() caplog.set_level(logging.DEBUG) app = MessageLoggerMiddleware(app) client = TestClient(app) with pytest.raises(RuntimeError): client.get("/") messages = [record.msg % record.args for record in caplog.records] assert sum(['ASGI [1] Initialized' in message for message in messages]) == 1 assert sum(['ASGI [1] Started task' in message for message in messages]) == 0 assert sum(['ASGI [1] Sent' in message for message in messages]) == 0 assert sum(['ASGI [1] Received' in message for message in messages]) == 0 assert sum(['ASGI [1] Completed' in message for message in messages]) == 0 assert sum( ['ASGI [1] Raised exception' in message for message in messages]) == 1
def run(self): app = self.wsgi if self.log.level <= logging.DEBUG: app = MessageLoggerMiddleware(app) loop = asyncio.get_event_loop() self.lifespan = Lifespan(app, self.log) if self.lifespan.is_enabled: loop.create_task(self.lifespan.run()) loop.run_until_complete(self.lifespan.wait_startup()) else: self.log.debug( "Lifespan protocol is not recognized by the application") loop.create_task(self.create_servers(loop, app)) loop.create_task(self.tick(loop)) loop.run_forever() sys.exit(self.exit_code)
def __init__( self, app, host="127.0.0.1", port=8000, uds=None, fd=None, loop="auto", http="auto", ws="auto", log_level="info", logger=None, access_log=True, wsgi=False, debug=False, proxy_headers=False, root_path="", limit_concurrency=None, limit_max_requests=None, disable_lifespan=False, timeout_keep_alive=5, install_signal_handlers=True, ): self.app = app self.host = host self.port = port self.uds = uds self.fd = fd self.loop = loop self.http = http self.ws = ws self.log_level = log_level self.logger = logger self.access_log = access_log self.wsgi = wsgi self.debug = debug self.proxy_headers = proxy_headers self.root_path = root_path self.limit_concurrency = limit_concurrency self.limit_max_requests = limit_max_requests self.disable_lifespan = disable_lifespan self.timeout_keep_alive = timeout_keep_alive self.install_signal_handlers = install_signal_handlers if fd is None: self.sock = None else: self.host = None self.port = None self.sock = socket.fromfd(fd, socket.AF_UNIX, socket.SOCK_STREAM) if self.logger is None: self.logger = get_logger(log_level) else: assert log_level == "info", "Cannot set both 'logger' and 'log_level'" if isinstance(http, str): self.http_protocol_class = import_from_string(HTTP_PROTOCOLS[http]) else: self.http_protocol_class = http if isinstance(ws, str): self.ws_protocol_class = import_from_string(WS_PROTOCOLS[ws]) else: self.ws_protocol_class = ws if isinstance(self.loop, str): loop_setup = import_from_string(LOOP_SETUPS[loop]) self.loop = loop_setup() try: self.app = import_from_string(self.app) except ImportFromStringError as exc: click.echo("Error loading ASGI app. %s" % exc) sys.exit(1) if self.wsgi: self.app = WSGIMiddleware(self.app) self.ws_protocol_class = None if self.debug: self.app = DebugMiddleware(self.app) if self.logger.level <= logging.DEBUG: self.app = MessageLoggerMiddleware(self.app) if self.proxy_headers: self.app = ProxyHeadersMiddleware(self.app)
def run( app, host="127.0.0.1", port=8000, uds=None, fd=None, loop="auto", http="auto", ws="auto", log_level="info", access_log=True, wsgi=False, debug=False, proxy_headers=False, root_path="", limit_concurrency=None, limit_max_requests=None, timeout_keep_alive=5, install_signal_handlers=True, ready_event=None, ): if fd is None: sock = None else: host = None port = None sock = socket.fromfd(fd, socket.AF_UNIX, socket.SOCK_STREAM) logger = get_logger(log_level) http_protocol_class = import_from_string(HTTP_PROTOCOLS[http]) ws_protocol_class = import_from_string(WS_PROTOCOLS[ws]) if isinstance(loop, str): loop_setup = import_from_string(LOOP_SETUPS[loop]) loop = loop_setup() try: app = import_from_string(app) except ImportFromStringError as exc: click.echo("Error loading ASGI app. %s" % exc) sys.exit(1) if wsgi: app = WSGIMiddleware(app) ws_protocol_class = None if debug: app = DebugMiddleware(app) if logger.level <= logging.DEBUG: app = MessageLoggerMiddleware(app) if proxy_headers: app = ProxyHeadersMiddleware(app) connections = set() tasks = set() state = {"total_requests": 0} def create_protocol(): return http_protocol_class( app=app, loop=loop, logger=logger, access_log=access_log, connections=connections, tasks=tasks, state=state, ws_protocol_class=ws_protocol_class, root_path=root_path, limit_concurrency=limit_concurrency, timeout_keep_alive=timeout_keep_alive, ) server = Server( app=app, host=host, port=port, uds=uds, sock=sock, logger=logger, loop=loop, connections=connections, tasks=tasks, state=state, limit_max_requests=limit_max_requests, create_protocol=create_protocol, on_tick=http_protocol_class.tick, install_signal_handlers=install_signal_handlers, ready_event=ready_event, ) server.run()
def load(self): assert not self.loaded if self.is_ssl: self.ssl = create_ssl_context( keyfile=self.ssl_keyfile, certfile=self.ssl_certfile, password=self.ssl_keyfile_password, ssl_version=self.ssl_version, cert_reqs=self.ssl_cert_reqs, ca_certs=self.ssl_ca_certs, ciphers=self.ssl_ciphers, ) else: self.ssl = None encoded_headers = [ (key.lower().encode("latin1"), value.encode("latin1")) for key, value in self.headers ] self.encoded_headers = ( encoded_headers if b"server" in dict(encoded_headers) else [(b"server", b"uvicorn")] + encoded_headers ) # type: List[Tuple[bytes, bytes]] if isinstance(self.http, str): self.http_protocol_class = import_from_string(HTTP_PROTOCOLS[self.http]) else: self.http_protocol_class = self.http if isinstance(self.ws, str): self.ws_protocol_class = import_from_string(WS_PROTOCOLS[self.ws]) else: self.ws_protocol_class = self.ws self.lifespan_class = import_from_string(LIFESPAN[self.lifespan]) try: self.loaded_app = import_from_string(self.app) except ImportFromStringError as exc: logger.error("Error loading ASGI app. %s" % exc) sys.exit(1) if self.interface == "auto": if inspect.isclass(self.loaded_app): use_asgi_3 = hasattr(self.loaded_app, "__await__") elif inspect.isfunction(self.loaded_app): use_asgi_3 = asyncio.iscoroutinefunction(self.loaded_app) else: call = getattr(self.loaded_app, "__call__", None) use_asgi_3 = asyncio.iscoroutinefunction(call) self.interface = "asgi3" if use_asgi_3 else "asgi2" if self.interface == "wsgi": self.loaded_app = WSGIMiddleware(self.loaded_app) self.ws_protocol_class = None elif self.interface == "asgi2": self.loaded_app = ASGI2Middleware(self.loaded_app) if self.debug: self.loaded_app = DebugMiddleware(self.loaded_app) if logger.level <= TRACE_LOG_LEVEL: self.loaded_app = MessageLoggerMiddleware(self.loaded_app) if self.proxy_headers: self.loaded_app = ProxyHeadersMiddleware( self.loaded_app, trusted_hosts=self.forwarded_allow_ips ) self.loaded = True
def load(self) -> None: assert not self.loaded if self.is_ssl: assert self.ssl_certfile self.ssl: Optional[ssl.SSLContext] = create_ssl_context( keyfile=self.ssl_keyfile, certfile=self.ssl_certfile, password=self.ssl_keyfile_password, ssl_version=self.ssl_version, cert_reqs=self.ssl_cert_reqs, ca_certs=self.ssl_ca_certs, ciphers=self.ssl_ciphers, ) else: self.ssl = None encoded_headers = [(key.lower().encode("latin1"), value.encode("latin1")) for key, value in self.headers] self.encoded_headers = ([(b"server", b"uvicorn")] + encoded_headers if b"server" not in dict(encoded_headers) and self.server_header else encoded_headers) if isinstance(self.http, str): http_protocol_class = import_from_string(HTTP_PROTOCOLS[self.http]) self.http_protocol_class: Type[ asyncio.Protocol] = http_protocol_class else: self.http_protocol_class = self.http if isinstance(self.ws, str): ws_protocol_class = import_from_string(WS_PROTOCOLS[self.ws]) self.ws_protocol_class: Optional[Type[ asyncio.Protocol]] = ws_protocol_class else: self.ws_protocol_class = self.ws self.lifespan_class = import_from_string(LIFESPAN[self.lifespan]) try: self.loaded_app = import_from_string(self.app) except ImportFromStringError as exc: logger.error("Error loading ASGI app. %s" % exc) sys.exit(1) try: self.loaded_app = self.loaded_app() except TypeError as exc: if self.factory: logger.error("Error loading ASGI app factory: %s", exc) sys.exit(1) else: if not self.factory: logger.warning( "ASGI app factory detected. Using it, " "but please consider setting the --factory flag explicitly." ) if self.interface == "auto": if inspect.isclass(self.loaded_app): use_asgi_3 = hasattr(self.loaded_app, "__await__") elif inspect.isfunction(self.loaded_app): use_asgi_3 = asyncio.iscoroutinefunction(self.loaded_app) else: call = getattr(self.loaded_app, "__call__", None) use_asgi_3 = asyncio.iscoroutinefunction(call) self.interface = "asgi3" if use_asgi_3 else "asgi2" if self.interface == "wsgi": self.loaded_app = WSGIMiddleware(self.loaded_app) self.ws_protocol_class = None elif self.interface == "asgi2": self.loaded_app = ASGI2Middleware(self.loaded_app) if self.debug: self.loaded_app = DebugMiddleware(self.loaded_app) if logger.level <= TRACE_LOG_LEVEL: self.loaded_app = MessageLoggerMiddleware(self.loaded_app) if self.proxy_headers: self.loaded_app = ProxyHeadersMiddleware( self.loaded_app, trusted_hosts=self.forwarded_allow_ips) self.loaded = True