Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions test_requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
websockets
31 changes: 31 additions & 0 deletions tests/test_sockjs_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import asyncio
import unittest
from multiprocessing import Process
import time
import websockets

from sockjstest.sockjs import app


class SockjsIntegrationTests(unittest.TestCase):
def setUp(self):
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(None)
self.server_process = Process(target=app.run, kwargs={'host': '127.0.0.1', 'port': 8080})
self.server_process.start()
time.sleep(1)

def tearDown(self):
self.server_process.terminate()
self.server_process.join()
self.loop.close()

def test_echo(self):
async def echo():
uri = "ws://127.0.0.1:8080/echo/websocket"
async with websockets.connect(uri) as websocket:
await websocket.send("Hello world!")
response = await websocket.recv()
self.assertEqual(response, "Hello world!")

self.loop.run_until_complete(echo())
10 changes: 4 additions & 6 deletions vase/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ def __init__(self, name):
self._name = name
self._routes = []

@asyncio.coroutine
def _handle_404(self, request, start_response):
async def _handle_404(self, request, start_response):
data = 'Not found'.encode('utf-8')
headers = (
(b'Content-Type', b'text/plain'),
Expand Down Expand Up @@ -67,16 +66,15 @@ def run(self, *, host='0.0.0.0', port=3000, loop=None):

def processor_factory(transport, protocol, reader, writer):
return RoutingHttpProcessor(transport, protocol, reader, writer, routes=self._routes)
asyncio.async(loop.create_server(lambda: BaseHttpProtocol(processor_factory, loop=loop),
asyncio.ensure_future(loop.create_server(lambda: BaseHttpProtocol(processor_factory, loop=loop),
host, port))
loop.run_forever()

@staticmethod
def _decorate_callback(callback):
@asyncio.coroutine
def handle_normal(request, start_response, **kwargs):
async def handle_normal(request, start_response, **kwargs):

data = yield from asyncio.coroutine(callback)(request, **kwargs)
data = await callback(request, **kwargs)
if isinstance(data, HttpResponse):
response = data
else:
Expand Down
21 changes: 10 additions & 11 deletions vase/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def __init__(self, request, reader, writer, callback):
self._writer = writer
self._callback = callback

def handle(self, **kwargs):
async def handle(self, **kwargs):
def start_response(status, headers):
self._writer.write_status(status)
self._writer.add_headers(*headers)
Expand All @@ -43,7 +43,7 @@ def write(data):
self._writer.write(data)
return write

result = yield from self._callback(self._request, start_response, **kwargs)
result = await self._callback(self._request, start_response, **kwargs)
self._writer.writelines(result)


Expand All @@ -56,14 +56,14 @@ def __init__(self, request, reader, writer, endpoint_factory, context):
self._endpoint = None
self._context = context

def handle(self, **kwargs):
async def handle(self, **kwargs):
self._endpoint = self._endpoint_factory()
self._endpoint.bag = self._context

self._endpoint.transport = WebSocketWriter(self._writer)

if hasattr(self._endpoint, 'authorize_request'):
if not (yield from asyncio.coroutine(self._endpoint.authorize_request)(self._request)):
if not await self._endpoint.authorize_request(self._request):
self._writer.write_status(b'401 Anauthorized')
self._writer.write_body(b'')
return
Expand All @@ -86,19 +86,18 @@ def handle(self, **kwargs):
)
self._writer.write_body(b'')

yield from self._switch_protocol()
await self._switch_protocol()

def _switch_protocol(self):
async def _switch_protocol(self):
self._endpoint.on_connect()

yield from self._parse_messages()
await self._parse_messages()

@asyncio.coroutine
def _parse_messages(self):
async def _parse_messages(self):
parser = WebSocketParser(self._reader)
while True:
try:
msg = yield from parser.get_message()
msg = await parser.get_message()
except WebSocketFormatException:
self._writer.close()
return
Expand All @@ -114,7 +113,7 @@ def _parse_messages(self):
elif msg.opcode == OpCode.ping:
self._writer.write(FrameBuilder.pong(masked=False, payload=msg.payload))
else:
yield from asyncio.coroutine(self._endpoint.on_message)(msg.payload)
await self._endpoint.on_message(msg.payload)

def persistent_connection(self):
return True
Expand Down
14 changes: 6 additions & 8 deletions vase/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,11 @@ def append_to_last_header(self, value):
def _has_form(self):
return self.get('content-type', '').lower() == _FORM_URLENCODED

@asyncio.coroutine
def _maybe_init_post(self):
async def _maybe_init_post(self):
if self._post_inited:
return
if self._has_form():
body = yield from self.body.read()
body = await self.body.read()
self.POST = MultiDict(urllib.parse.parse_qs(body.decode('utf-8')))
self._post_inited = True

Expand Down Expand Up @@ -200,9 +199,8 @@ def _write_chunk(self, data):

class HttpParser:
@staticmethod
@asyncio.coroutine
def parse(reader):
l = yield from reader.readline()
async def parse(reader):
l = await reader.readline()
if not l:
return
l = l.rstrip(DELIMITER)
Expand All @@ -224,7 +222,7 @@ def parse(reader):
request = HttpRequest(method, uri, version, extra)

while True:
l = yield from reader.readline()
l = await reader.readline()
if not l:
return
if l == DELIMITER:
Expand All @@ -243,5 +241,5 @@ def parse(reader):
request.append_to_last_header(value)

request.body = reader
yield from request._maybe_init_post()
await request._maybe_init_post()
return request
16 changes: 7 additions & 9 deletions vase/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ def __init__(self, transport, protocol, reader, writer):
self._reader = reader
self._writer = writer

@asyncio.coroutine
def handle_request(self, request):
async def handle_request(self, request):
self._transport.write(b'HTTP/1.1 404 NOT FOUND\r\nContent-Length: 13\r\n\r\n404 Not Found')

def on_timeout(self):
Expand Down Expand Up @@ -50,7 +49,7 @@ def connection_made(self, transport):

self._handler = self._build_handler()

self._task = asyncio.async(self._handle_client())
self._task = asyncio.ensure_future(self._handle_client())
self._task.add_done_callback(self._maybe_log_exception)

self._reset_timeout()
Expand All @@ -71,11 +70,10 @@ def data_received(self, data):
self._reset_timeout()
super().data_received(data)

@asyncio.coroutine
def _handle_client(self):
async def _handle_client(self):
while True:
try:
req = yield from HttpParser.parse(self._reader)
req = await HttpParser.parse(self._reader)
except BadRequestException as e:
self._bad_request(self._writer, e)
self._writer.close()
Expand All @@ -85,13 +83,13 @@ def _handle_client(self):
break

try:
yield from self._handler.handle_request(req)
await self._handler.handle_request(req)
finally:
if self._should_close_conn_immediately(req):
if self._writer:
self._writer.close()
else:
yield from req.body.read()
await req.body.read()
if self._writer is not None:
self._writer.restore()

Expand Down Expand Up @@ -144,6 +142,6 @@ def _maybe_log_exception(self, task):
if __name__ == '__main__': # pragma: no cover
loop = asyncio.get_event_loop()
host, port = 'localhost', 3000
asyncio.async(loop.create_server(lambda: BaseHttpProtocol(loop=loop),
asyncio.ensure_future(loop.create_server(lambda: BaseHttpProtocol(loop=loop),
host, port))
loop.run_forever()
9 changes: 4 additions & 5 deletions vase/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ def __init__(self, transport, protocol, reader, writer, *, routes=None):
self._handler = None
super().__init__(transport, protocol, reader, writer)

@asyncio.coroutine
def handle_request(self, request):
async def handle_request(self, request):
current_route = None
matchdict = {}
for route in self._routes:
Expand All @@ -22,10 +21,10 @@ def handle_request(self, request):
current_route = route
break
if current_route is None:
return (yield from super().handle_request(request))
return await super().handle_request(request)
self._handler = current_route.handler_factory(request, self._reader, self._writer)

return (yield from self._handler.handle(**matchdict))
return await self._handler.handle(**matchdict)

def on_timeout(self):
self._handler.on_timeout()
Expand Down Expand Up @@ -53,7 +52,7 @@ def __str__(self):
)


_R = re.compile("{((\w+:)?[^{}]+)}")
_R = re.compile(r"{((\w+:)?[^{}]+)}")


def _regex_substituter(m):
Expand Down
23 changes: 10 additions & 13 deletions vase/sockjs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,11 @@ def __init__(self, name):
def attach(self, endpoint):
self.endpoint = endpoint

@asyncio.coroutine
def consume(self):
async def consume(self):
if self.endpoint:
while self.pending_messages:
msg = self.pending_messages.popleft()
yield from asyncio.coroutine(self.endpoint.on_message)(msg)
await self.endpoint.on_message(msg)


class SockJsRoute(ContextHandlingCallbackRoute):
Expand Down Expand Up @@ -95,8 +94,7 @@ def __init__(self, request, reader, writer, endpoint, context, sessions):

self._session = None

@asyncio.coroutine
def handle(self, **kwargs):
async def handle(self, **kwargs):
path = kwargs.pop(SockJsRoute.SOCKJS_ROUTE_MATCH, '')
if not path or path == '/':
self._writer.status = 200
Expand All @@ -108,13 +106,13 @@ def handle(self, **kwargs):
self._writer.write_body(content)
return
if path == '/info':
yield from self._info_handler.handle(self._request, self._writer)
await self._info_handler.handle(self._request, self._writer)
return
elif self._iframe_handler.path_re.match(path):
yield from self._iframe_handler.handle(self._request, self._writer)
await self._iframe_handler.handle(self._request, self._writer)
return
elif path == '/websocket':
yield from self._ws_handler.handle(self._request, self._writer)
await self._ws_handler.handle(self._request, self._writer)
return
else:
parts = path[1:].split("/")
Expand All @@ -124,7 +122,7 @@ def handle(self, **kwargs):
server, session, transport = parts
if not self._validate_parts(server, session, transport):
return self.not_found()
return (yield from self._handle_transport(session, transport))
return await self._handle_transport(session, transport)

def _validate_parts(self, server, session, transport):
if not server or not session or not transport:
Expand All @@ -135,8 +133,7 @@ def _validate_parts(self, server, session, transport):
return False
return True

@asyncio.coroutine
def _handle_transport(self, session, transport):
async def _handle_transport(self, session, transport):
handler = self._transport_handlers.get(transport)
if handler is None:
return self.not_found()
Expand All @@ -152,7 +149,7 @@ def _handle_transport(self, session, transport):
else:
endpoint = self._instantiate_endpoint()
if hasattr(endpoint, 'authorize_request'):
if not (yield from asyncio.coroutine(sess.authorize_request)(self._request)):
if not await sess.authorize_request(self._request):
self._writer.status = 401
self._writer.write_body('')
return
Expand All @@ -174,7 +171,7 @@ def _handle_transport(self, session, transport):

handler = handler(self._request, sess, self._context)
self._current_handler = handler
yield from handler.handle(self._request, self._writer)
await handler.handle(self._request, self._writer)

def _instantiate_endpoint(self):
end = self._endpoint()
Expand Down
Loading