From 481c4b6772e74ef10fbac91a594e891befadd6f6 Mon Sep 17 00:00:00 2001 From: SAY-5 Date: Sat, 2 May 2026 15:17:34 -0700 Subject: [PATCH] fix: skip Content-Type gate when request is None (#2843) Legacy-UI batch flows invoke route handlers internally with request=None, which previously raised AttributeError on request.content_type. Signed-off-by: SAY-5 --- glob/manager_server.py | 6 +++++- tests/test_csrf_content_type_helper.py | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/glob/manager_server.py b/glob/manager_server.py index 8474bb9c..2b97cb23 100644 --- a/glob/manager_server.py +++ b/glob/manager_server.py @@ -353,8 +353,12 @@ def _reject_simple_form_content_type(request): web.Response(status=400) when the request has a simple-form Content-Type that must be rejected. None when the request is allowed to proceed (no Content-Type, application/json, or any non-simple - Content-Type). + Content-Type, or no request object — internal caller). """ + # Internal callers (e.g. legacy-UI batch flows) invoke route handlers + # directly with request=None; there is no Content-Type to gate. + if request is None: + return None if request.content_type in _SIMPLE_FORM_CONTENT_TYPES: return web.Response( status=400, diff --git a/tests/test_csrf_content_type_helper.py b/tests/test_csrf_content_type_helper.py index e1467475..f2e67482 100644 --- a/tests/test_csrf_content_type_helper.py +++ b/tests/test_csrf_content_type_helper.py @@ -116,6 +116,12 @@ class ContentTypeRejectionTest(unittest.TestCase): r = self._post({"Content-Type": "application/json"}) self.assertEqual(r.status, 200) + def test_none_request_allowed(self): + # Internal callers (e.g. legacy-UI batch flows) invoke route handlers + # directly with request=None; helper must not raise AttributeError. + # Regression test for issue #2843. + self.assertIsNone(_reject_simple_form_content_type(None)) + if __name__ == "__main__": unittest.main(verbosity=2)