Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

129 строки
3.7KB

  1. import asyncio
  2. import sys
  3. from urllib.parse import urlsplit
  4. from aiohttp.web import Response, WebSocketResponse
  5. import six
  6. def create_route(app, engineio_server, engineio_endpoint):
  7. """This function sets up the engine.io endpoint as a route for the
  8. application.
  9. Note that both GET and POST requests must be hooked up on the engine.io
  10. endpoint.
  11. """
  12. app.router.add_get(engineio_endpoint, engineio_server.handle_request)
  13. app.router.add_post(engineio_endpoint, engineio_server.handle_request)
  14. app.router.add_route('OPTIONS', engineio_endpoint,
  15. engineio_server.handle_request)
  16. def translate_request(request):
  17. """This function takes the arguments passed to the request handler and
  18. uses them to generate a WSGI compatible environ dictionary.
  19. """
  20. message = request._message
  21. payload = request._payload
  22. uri_parts = urlsplit(message.path)
  23. environ = {
  24. 'wsgi.input': payload,
  25. 'wsgi.errors': sys.stderr,
  26. 'wsgi.version': (1, 0),
  27. 'wsgi.async': True,
  28. 'wsgi.multithread': False,
  29. 'wsgi.multiprocess': False,
  30. 'wsgi.run_once': False,
  31. 'SERVER_SOFTWARE': 'aiohttp',
  32. 'REQUEST_METHOD': message.method,
  33. 'QUERY_STRING': uri_parts.query or '',
  34. 'RAW_URI': message.path,
  35. 'SERVER_PROTOCOL': 'HTTP/%s.%s' % message.version,
  36. 'REMOTE_ADDR': '127.0.0.1',
  37. 'REMOTE_PORT': '0',
  38. 'SERVER_NAME': 'aiohttp',
  39. 'SERVER_PORT': '0',
  40. 'aiohttp.request': request
  41. }
  42. for hdr_name, hdr_value in message.headers.items():
  43. hdr_name = hdr_name.upper()
  44. if hdr_name == 'CONTENT-TYPE':
  45. environ['CONTENT_TYPE'] = hdr_value
  46. continue
  47. elif hdr_name == 'CONTENT-LENGTH':
  48. environ['CONTENT_LENGTH'] = hdr_value
  49. continue
  50. key = 'HTTP_%s' % hdr_name.replace('-', '_')
  51. if key in environ:
  52. hdr_value = '%s,%s' % (environ[key], hdr_value)
  53. environ[key] = hdr_value
  54. environ['wsgi.url_scheme'] = environ.get('HTTP_X_FORWARDED_PROTO', 'http')
  55. path_info = uri_parts.path
  56. environ['PATH_INFO'] = path_info
  57. environ['SCRIPT_NAME'] = ''
  58. return environ
  59. def make_response(status, headers, payload, environ):
  60. """This function generates an appropriate response object for this async
  61. mode.
  62. """
  63. return Response(body=payload, status=int(status.split()[0]),
  64. headers=headers)
  65. class WebSocket(object): # pragma: no cover
  66. """
  67. This wrapper class provides a aiohttp WebSocket interface that is
  68. somewhat compatible with eventlet's implementation.
  69. """
  70. def __init__(self, handler):
  71. self.handler = handler
  72. self._sock = None
  73. async def __call__(self, environ):
  74. request = environ['aiohttp.request']
  75. self._sock = WebSocketResponse()
  76. await self._sock.prepare(request)
  77. self.environ = environ
  78. await self.handler(self)
  79. return self._sock
  80. async def close(self):
  81. await self._sock.close()
  82. async def send(self, message):
  83. if isinstance(message, bytes):
  84. f = self._sock.send_bytes
  85. else:
  86. f = self._sock.send_str
  87. if asyncio.iscoroutinefunction(f):
  88. await f(message)
  89. else:
  90. f(message)
  91. async def wait(self):
  92. msg = await self._sock.receive()
  93. if not isinstance(msg.data, six.binary_type) and \
  94. not isinstance(msg.data, six.text_type):
  95. raise IOError()
  96. return msg.data
  97. _async = {
  98. 'asyncio': True,
  99. 'create_route': create_route,
  100. 'translate_request': translate_request,
  101. 'make_response': make_response,
  102. 'websocket': WebSocket,
  103. }