File: aiohttp.py

package info (click to toggle)
python-engineio 4.13.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 948 kB
  • sloc: python: 10,660; makefile: 15; sh: 6
file content (120 lines) | stat: -rw-r--r-- 3,624 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import inspect
import sys

from aiohttp.web import Response, WebSocketResponse


def create_route(app, engineio_server, engineio_endpoint):
    """This function sets up the engine.io endpoint as a route for the
    application.

    Note that both GET and POST requests must be hooked up on the engine.io
    endpoint.
    """
    app.router.add_get(engineio_endpoint, engineio_server.handle_request)
    app.router.add_post(engineio_endpoint, engineio_server.handle_request)
    app.router.add_route('OPTIONS', engineio_endpoint,
                         engineio_server.handle_request)


def translate_request(request):
    """This function takes the arguments passed to the request handler and
    uses them to generate a WSGI compatible environ dictionary.
    """
    environ = {
        'wsgi.input': request.content,
        'wsgi.errors': sys.stderr,
        'wsgi.version': (1, 0),
        'wsgi.async': True,
        'wsgi.multithread': False,
        'wsgi.multiprocess': False,
        'wsgi.run_once': False,
        'SERVER_SOFTWARE': 'aiohttp',
        'REQUEST_METHOD': request.method,
        'QUERY_STRING': request.query_string or '',
        'RAW_URI': request.path_qs,
        'SERVER_PROTOCOL': f'HTTP/{request.version[0]}.{request.version[1]}',
        'REMOTE_ADDR': '127.0.0.1',
        'REMOTE_PORT': '0',
        'SERVER_NAME': 'aiohttp',
        'SERVER_PORT': '0',
        'aiohttp.request': request
    }

    for hdr_name, hdr_value in request.headers.items():
        hdr_name = hdr_name.upper()
        if hdr_name == 'CONTENT-TYPE':
            environ['CONTENT_TYPE'] = hdr_value
            continue
        elif hdr_name == 'CONTENT-LENGTH':
            environ['CONTENT_LENGTH'] = hdr_value
            continue

        key = 'HTTP_%s' % hdr_name.replace('-', '_')
        if key in environ:
            hdr_value = f'{environ[key]},{hdr_value}'

        environ[key] = hdr_value

    environ['wsgi.url_scheme'] = environ.get('HTTP_X_FORWARDED_PROTO', 'http')

    environ['PATH_INFO'] = request.path
    environ['SCRIPT_NAME'] = ''

    return environ


def make_response(status, headers, payload, environ):
    """This function generates an appropriate response object for this async
    mode.
    """
    return Response(body=payload, status=int(status.split()[0]),
                    headers=headers)


class WebSocket:  # pragma: no cover
    """
    This wrapper class provides a aiohttp WebSocket interface that is
    somewhat compatible with eventlet's implementation.
    """
    def __init__(self, handler, server):
        self.handler = handler
        self._sock = None

    async def __call__(self, environ):
        request = environ['aiohttp.request']
        self._sock = WebSocketResponse(max_msg_size=0)
        await self._sock.prepare(request)

        self.environ = environ
        await self.handler(self)
        return self._sock

    async def close(self):
        await self._sock.close()

    async def send(self, message):
        if isinstance(message, bytes):
            f = self._sock.send_bytes
        else:
            f = self._sock.send_str
        if inspect.iscoroutinefunction(f):
            await f(message)
        else:
            f(message)

    async def wait(self):
        msg = await self._sock.receive()
        if not isinstance(msg.data, bytes) and \
                not isinstance(msg.data, str):
            raise OSError()
        return msg.data


_async = {
    'asyncio': True,
    'create_route': create_route,
    'translate_request': translate_request,
    'make_response': make_response,
    'websocket': WebSocket,
}