Skip to content

Commit 8698661

Browse files
ericapisaniclaude
andcommitted
ref(wsgi): Simplify file response bypass to not require uWSGI offload-threads check
Remove the _is_uwsgi_offload_threads_enabled() helper and the associated uWSGI import. The broader condition — skip wrapping whenever wsgi.file_wrapper is present and the response is file-like (has fileno) — is sufficient and correct since uWSGI applies file-handling optimizations beyond just offload-threads. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent e1b733b commit 8698661

File tree

2 files changed

+24
-59
lines changed

2 files changed

+24
-59
lines changed

sentry_sdk/integrations/wsgi.py

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -145,41 +145,22 @@ def __call__(
145145
# To avoid this and ensure that the offloading mechanism works as expected when it's
146146
# enabled, we check if the response is a file-like object (determined by the presence
147147
# of `fileno`), if the wsgi.file_wrapper is available in the environment (as if so,
148-
# it would've been used in handling the file in the response), and if uWSGI's
149-
# offload-threads option is configured (since offloading only occurs when offload
150-
# threads are enabled).
148+
# it would've been used in handling the file in the response).
149+
#
150+
# Even if the offload mechanism is not enabled, there are optimizations that uWSGI does for file-like objects,
151+
# so we want to make sure we don't interfere with those either.
151152
#
152153
# If all conditions are met, we return the original response object directly,
153154
# allowing uWSGI to handle it as intended.
154155
if (
155-
_is_uwsgi_offload_threads_enabled()
156-
and environ.get("wsgi.file_wrapper")
156+
environ.get("wsgi.file_wrapper")
157157
and getattr(response, "fileno", None) is not None
158158
):
159159
return response
160160

161161
return _ScopedResponse(scope, response)
162162

163163

164-
def _is_uwsgi_offload_threads_enabled() -> bool:
165-
try:
166-
from uwsgi import opt # type: ignore
167-
except ImportError:
168-
return False
169-
170-
value = opt.get("offload-threads") or opt.get(b"offload-threads")
171-
if not value:
172-
return False
173-
if isinstance(value, bytes):
174-
try:
175-
return int(value.decode()) > 0
176-
except (ValueError, UnicodeDecodeError):
177-
return False
178-
if isinstance(value, int):
179-
return value > 0
180-
return False
181-
182-
183164
def _sentry_start_response(
184165
old_start_response: "StartResponse",
185166
transaction: "Optional[Transaction]",

tests/integrations/wsgi/test_wsgi.py

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -503,24 +503,16 @@ def dogpark(environ, start_response):
503503

504504

505505
@pytest.mark.parametrize(
506-
"uwsgi_opt, has_file_wrapper, has_fileno, expect_wrapped",
506+
"has_file_wrapper, has_fileno, expect_wrapped",
507507
[
508-
({"offload-threads": 1}, True, True, False), # all conditions met → unwrapped
509-
({"offload-threads": 0}, True, True, True), # offload disabled → wrapped
510-
({"offload-threads": 1}, False, True, True), # no file_wrapper → wrapped
511-
({"offload-threads": 1}, True, False, True), # no fileno → wrapped
512-
(None, True, True, True), # uwsgi not installed → wrapped
513-
({"offload-threads": b"1"}, True, True, False), # bytes value → unwrapped
514-
(
515-
{b"offload-threads": b"1"},
516-
True,
517-
True,
518-
False,
519-
), # bytes key + bytes value → unwrapped
508+
(True, True, False), # both conditions met → unwrapped
509+
(False, True, True), # no file_wrapper → wrapped
510+
(True, False, True), # no fileno → wrapped
511+
(False, False, True), # neither condition → wrapped
520512
],
521513
)
522-
def test_uwsgi_offload_threads_response_wrapping(
523-
sentry_init, uwsgi_opt, has_file_wrapper, has_fileno, expect_wrapped
514+
def test_file_response_wrapping(
515+
sentry_init, has_file_wrapper, has_fileno, expect_wrapped
524516
):
525517
sentry_init()
526518

@@ -538,26 +530,18 @@ def app(environ, start_response):
538530

539531
middleware = SentryWsgiMiddleware(app)
540532

541-
if uwsgi_opt is not None:
542-
uwsgi_mock = mock.MagicMock()
543-
uwsgi_mock.opt = uwsgi_opt
544-
patch_ctx = mock.patch.dict("sys.modules", uwsgi=uwsgi_mock)
545-
else:
546-
patch_ctx = mock.patch.dict("sys.modules", {"uwsgi": None})
547-
548-
with patch_ctx:
549-
result = middleware(
550-
{
551-
"REQUEST_METHOD": "GET",
552-
"PATH_INFO": "/",
553-
"SERVER_NAME": "localhost",
554-
"SERVER_PORT": "80",
555-
"wsgi.url_scheme": "http",
556-
"wsgi.input": mock.MagicMock(),
557-
**environ_extra,
558-
},
559-
lambda status, headers: None,
560-
)
533+
result = middleware(
534+
{
535+
"REQUEST_METHOD": "GET",
536+
"PATH_INFO": "/",
537+
"SERVER_NAME": "localhost",
538+
"SERVER_PORT": "80",
539+
"wsgi.url_scheme": "http",
540+
"wsgi.input": mock.MagicMock(),
541+
**environ_extra,
542+
},
543+
lambda status, headers: None,
544+
)
561545

562546
if expect_wrapped:
563547
assert isinstance(result, _ScopedResponse)

0 commit comments

Comments
 (0)