I am developing a web server using flask 2.0.2 and deploying using hypercorn. I want to deploy it as asgi application.
My main.py looks like this:
from flask import Flask
from asgiref.wsgi import WsgiToAsgi
app = Flask(__name__)
@app.get("/")
async def hello_word():
await asyncio.sleep(1)
return "<p> Hello World </p>"
asgi_app = WsgiToAsgi(app)
When deploying the server: hypercorn main:asgi_app
The following error is raised but the server is deployed successfully.
[2021-11-29 20:15:30 +0530] [41394] [ERROR] ASGI Framework Lifespan error, continuing without Lifespan support
Traceback (most recent call last):
File "/PycharmProjects/MyProject/venv/lib/python3.7/site-packages/hypercorn/asyncio/lifespan.py", line 32, in handle_lifespan
await invoke_asgi(self.app, scope, self.asgi_receive, self.asgi_send)
File "/PycharmProjects/MyProject/venv/lib/python3.7/site-packages/hypercorn/utils.py", line 246, in invoke_asgi
await app(scope, receive, send)
File "/PycharmProjects/MyProject/venv/lib/python3.7/site-packages/asgiref/wsgi.py", line 21, in __call__
await WsgiToAsgiInstance(self.wsgi_application)(scope, receive, send)
File "/PycharmProjects/MyProject/venv/lib/python3.7/site-packages/asgiref/wsgi.py", line 36, in __call__
raise ValueError("WSGI wrapper received a non-HTTP scope")
ValueError: WSGI wrapper received a non-HTTP scope
[2021-11-29 20:15:30 +0530] [41394] [INFO] Running on http://127.0.0.1:8000 (CTRL + C to quit)
I am able to hit the route defined but the cause of this error is still unknown to me. On looking into the stack trace, i found that when deploying the handle_lifespan function in hypercorn/asyncio/lifespan.py is called which looks like this:
async def handle_lifespan(self) -> None:
self._started.set()
scope: LifespanScope = {"type": "lifespan", "asgi": {"spec_version": "2.0"}}
try:
await invoke_asgi(self.app, scope, self.asgi_receive, self.asgi_send)
except LifespanFailureError:
# Lifespan failures should crash the server
raise
except Exception:
self.supported = False
if not self.startup.is_set():
message = "ASGI Framework Lifespan error, continuing without Lifespan support"
elif not self.shutdown.is_set():
message = "ASGI Framework Lifespan error, shutdown without Lifespan support"
else:
message = "ASGI Framework Lifespan errored after shutdown."
await self.config.log.exception(message)
finally:
self.startup.set()
self.shutdown.set()
This defines the scope type as "lifespan" and passes this scope to the WsgiToAsgiInstance class that checks the scope of the request:
if scope["type"] != "http":
raise ValueError("WSGI wrapper received a non-HTTP scope")
Can someone help me understanding it better?