Skip to content

Commit 0b8db27

Browse files
authored
fix: Make ASGI middleware inspectable for ASGI version (getsentry#557)
* fix: Make ASGI middleware inspectable for ASGI version * fix: Linters
1 parent 3b00f57 commit 0b8db27

File tree

1 file changed

+34
-12
lines changed

1 file changed

+34
-12
lines changed

sentry_sdk/integrations/asgi.py

+34-12
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
Based on Tom Christie's `sentry-asgi <https://github.com/encode/sentry-asgi>`_.
55
"""
66

7+
import asyncio
78
import functools
9+
import inspect
810
import urllib
911

1012
from sentry_sdk._types import MYPY
@@ -17,6 +19,7 @@
1719
from typing import Dict
1820
from typing import Any
1921
from typing import Optional
22+
from typing import Callable
2023

2124
from sentry_sdk._types import Event, Hint
2225

@@ -37,26 +40,45 @@ def _capture_exception(hub, exc):
3740
hub.capture_event(event, hint=hint)
3841

3942

43+
def _looks_like_asgi3(app):
44+
# type: (Any) -> bool
45+
"""
46+
Try to figure out if an application object supports ASGI3.
47+
48+
This is how uvicorn figures out the application version as well.
49+
"""
50+
if inspect.isclass(app):
51+
return hasattr(app, "__await__")
52+
elif inspect.isfunction(app):
53+
return asyncio.iscoroutinefunction(app)
54+
else:
55+
call = getattr(app, "__call__", None) # noqa
56+
return asyncio.iscoroutinefunction(call)
57+
58+
4059
class SentryAsgiMiddleware:
41-
__slots__ = ("app",)
60+
__slots__ = ("app", "__call__")
4261

4362
def __init__(self, app):
4463
# type: (Any) -> None
4564
self.app = app
4665

47-
def __call__(self, scope, receive=None, send=None):
48-
# type: (Any, Any, Any) -> Any
49-
if receive is None or send is None:
66+
if _looks_like_asgi3(app):
67+
self.__call__ = self._run_asgi3 # type: Callable[..., Any]
68+
else:
69+
self.__call__ = self._run_asgi2
5070

51-
async def run_asgi2(receive, send):
52-
# type: (Any, Any) -> Any
53-
return await self._run_app(
54-
scope, lambda: self.app(scope)(receive, send)
55-
)
71+
def _run_asgi2(self, scope):
72+
# type: (Any) -> Any
73+
async def inner(receive, send):
74+
# type: (Any, Any) -> Any
75+
return await self._run_app(scope, lambda: self.app(scope)(receive, send))
5676

57-
return run_asgi2
58-
else:
59-
return self._run_app(scope, lambda: self.app(scope, receive, send))
77+
return inner
78+
79+
async def _run_asgi3(self, scope, receive, send):
80+
# type: (Any, Any, Any) -> Any
81+
return await self._run_app(scope, lambda: self.app(scope, receive, send))
6082

6183
async def _run_app(self, scope, callback):
6284
# type: (Any, Any) -> Any

0 commit comments

Comments
 (0)