MCPcopy
hub / github.com/django/django / test_cancel_post_request_with_sync_processing

Method test_cancel_post_request_with_sync_processing

tests/asgi/tests.py:297–354  ·  view source on GitHub ↗

The request.body object should be available and readable in view code, even if the ASGIHandler cancels processing part way through.

(self)

Source from the content-addressed store, hash-verified

295 self.assertNotIn("HTTP_SOME_HEADER", request.META)
296
297 async def test_cancel_post_request_with_sync_processing(self):
298 """
299 The request.body object should be available and readable in view
300 code, even if the ASGIHandler cancels processing part way through.
301 """
302 loop = asyncio.get_event_loop()
303 # Events to monitor the view processing from the parent test code.
304 view_started_event = asyncio.Event()
305 view_finished_event = asyncio.Event()
306 # Record received request body or exceptions raised in the test view
307 outcome = []
308
309 # This view will run in a new thread because it is wrapped in
310 # sync_to_async. The view consumes the POST body data after a short
311 # delay. The test will cancel the request using http.disconnect during
312 # the delay, but because this is a sync view the code runs to
313 # completion. There should be no exceptions raised inside the view
314 # code.
315 @csrf_exempt
316 @sync_to_async
317 def post_view(request):
318 try:
319 loop.call_soon_threadsafe(view_started_event.set)
320 time.sleep(0.1)
321 # Do something to read request.body after pause
322 outcome.append({"request_body": request.body})
323 return HttpResponse("ok")
324 except Exception as e:
325 outcome.append({"exception": e})
326 finally:
327 loop.call_soon_threadsafe(view_finished_event.set)
328
329 # Request class to use the view.
330 class TestASGIRequest(ASGIRequest):
331 urlconf = (path("post/", post_view),)
332
333 # Handler to use request class.
334 class TestASGIHandler(ASGIHandler):
335 request_class = TestASGIRequest
336
337 application = TestASGIHandler()
338 scope = self.async_request_factory._base_scope(
339 method="POST",
340 path="/post/",
341 )
342 communicator = ApplicationCommunicator(application, scope)
343
344 await communicator.send_input({"type": "http.request", "body": b"Body data!"})
345
346 # Wait until the view code has started, then send http.disconnect.
347 await view_started_event.wait()
348 await communicator.send_input({"type": "http.disconnect"})
349 # Wait until view code has finished.
350 await view_finished_event.wait()
351 with self.assertRaises(asyncio.TimeoutError):
352 await communicator.receive_output()
353
354 self.assertEqual(outcome, [{"request_body": b"Body data!"}])

Callers

nothing calls this directly

Calls 2

TestASGIHandlerClass · 0.85
_base_scopeMethod · 0.80

Tested by

no test coverage detected