Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1 year ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. from channels.consumer import AsyncConsumer
  2. from ..exceptions import StopConsumer
  3. class AsyncHttpConsumer(AsyncConsumer):
  4. """
  5. Async HTTP consumer. Provides basic primitives for building asynchronous
  6. HTTP endpoints.
  7. """
  8. def __init__(self, *args, **kwargs):
  9. self.body = []
  10. async def send_headers(self, *, status=200, headers=None):
  11. """
  12. Sets the HTTP response status and headers. Headers may be provided as
  13. a list of tuples or as a dictionary.
  14. Note that the ASGI spec requires that the protocol server only starts
  15. sending the response to the client after ``self.send_body`` has been
  16. called the first time.
  17. """
  18. if headers is None:
  19. headers = []
  20. elif isinstance(headers, dict):
  21. headers = list(headers.items())
  22. await self.send(
  23. {"type": "http.response.start", "status": status, "headers": headers}
  24. )
  25. async def send_body(self, body, *, more_body=False):
  26. """
  27. Sends a response body to the client. The method expects a bytestring.
  28. Set ``more_body=True`` if you want to send more body content later.
  29. The default behavior closes the response, and further messages on
  30. the channel will be ignored.
  31. """
  32. assert isinstance(body, bytes), "Body is not bytes"
  33. await self.send(
  34. {"type": "http.response.body", "body": body, "more_body": more_body}
  35. )
  36. async def send_response(self, status, body, **kwargs):
  37. """
  38. Sends a response to the client. This is a thin wrapper over
  39. ``self.send_headers`` and ``self.send_body``, and everything said
  40. above applies here as well. This method may only be called once.
  41. """
  42. await self.send_headers(status=status, **kwargs)
  43. await self.send_body(body)
  44. async def handle(self, body):
  45. """
  46. Receives the request body as a bytestring. Response may be composed
  47. using the ``self.send*`` methods; the return value of this method is
  48. thrown away.
  49. """
  50. raise NotImplementedError(
  51. "Subclasses of AsyncHttpConsumer must provide a handle() method."
  52. )
  53. async def disconnect(self):
  54. """
  55. Overrideable place to run disconnect handling. Do not send anything
  56. from here.
  57. """
  58. pass
  59. async def http_request(self, message):
  60. """
  61. Async entrypoint - concatenates body fragments and hands off control
  62. to ``self.handle`` when the body has been completely received.
  63. """
  64. if "body" in message:
  65. self.body.append(message["body"])
  66. if not message.get("more_body"):
  67. try:
  68. await self.handle(b"".join(self.body))
  69. finally:
  70. await self.disconnect()
  71. raise StopConsumer()
  72. async def http_disconnect(self, message):
  73. """
  74. Let the user do their cleanup and close the consumer.
  75. """
  76. await self.disconnect()
  77. raise StopConsumer()