diff --git a/docs/index.rst b/docs/index.rst index 9f4fa00c..aaa296ee 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -14,6 +14,7 @@ Guides sanic/exceptions sanic/middleware sanic/blueprints + sanic/websocket sanic/config sanic/cookies sanic/decorators diff --git a/docs/sanic/websocket.rst b/docs/sanic/websocket.rst new file mode 100644 index 00000000..8b813bf8 --- /dev/null +++ b/docs/sanic/websocket.rst @@ -0,0 +1,51 @@ +WebSocket +========= + +Sanic supports websockets, to setup a WebSocket: + +.. code:: python + + from sanic import Sanic + from sanic.response import json + from sanic.websocket import WebSocketProtocol + + app = Sanic() + + @app.websocket('/feed') + async def feed(request, ws): + while True: + data = 'hello!' + print('Sending: ' + data) + await ws.send(data) + data = await ws.recv() + print('Received: ' + data) + + if __name__ == "__main__": + app.run(host="0.0.0.0", port=8000, protocol=WebSocketProtocol) + + +Alternatively, the ``app.add_websocket_route`` method can be used instead of the +decorator: + +.. code:: python + + async def feed(request, ws): + pass + + app.add_websocket_route(feed, '/feed') + + +Handlers for a WebSocket route are passed the request as first argument, and a +WebSocket protocol object as second argument. The protocol object has ``send`` +and ``recv`` methods to send and receive data respectively. + + +You could setup your own WebSocket configuration through ``app.config``, like + +.. code:: python + app.config.WEBSOCKET_MAX_SIZE = 2 ** 20 + app.config.WEBSOCKET_MAX_QUEUE = 32 + app.config.WEBSOCKET_READ_LIMIT = 2 ** 16 + app.config.WEBSOCKET_WRITE_LIMIT = 2 ** 16 + +Find more in ``Configuration`` section. diff --git a/sanic/app.py b/sanic/app.py index 6e8377f5..1513e467 100644 --- a/sanic/app.py +++ b/sanic/app.py @@ -807,6 +807,8 @@ class Sanic: 'access_log': access_log, 'websocket_max_size': self.config.WEBSOCKET_MAX_SIZE, 'websocket_max_queue': self.config.WEBSOCKET_MAX_QUEUE, + 'websocket_read_limit': self.config.WEBSOCKET_READ_LIMIT, + 'websocket_write_limit': self.config.WEBSOCKET_WRITE_LIMIT, 'graceful_shutdown_timeout': self.config.GRACEFUL_SHUTDOWN_TIMEOUT } diff --git a/sanic/config.py b/sanic/config.py index 922a9874..8e1f383c 100644 --- a/sanic/config.py +++ b/sanic/config.py @@ -36,6 +36,8 @@ class Config(dict): self.KEEP_ALIVE_TIMEOUT = 5 # 5 seconds self.WEBSOCKET_MAX_SIZE = 2 ** 20 # 1 megabytes self.WEBSOCKET_MAX_QUEUE = 32 + self.WEBSOCKET_READ_LIMIT = 2 ** 16 + self.WEBSOCKET_WRITE_LIMIT = 2 ** 16 self.GRACEFUL_SHUTDOWN_TIMEOUT = 15.0 # 15 sec if load_env: diff --git a/sanic/server.py b/sanic/server.py index 10a9040a..15ae4708 100644 --- a/sanic/server.py +++ b/sanic/server.py @@ -514,6 +514,7 @@ def serve(host, port, request_handler, error_handler, before_start=None, connections=None, signal=Signal(), request_class=None, access_log=True, keep_alive=True, is_request_stream=False, router=None, websocket_max_size=None, websocket_max_queue=None, + websocket_read_limit=2 ** 16, websocket_write_limit=2 ** 16, state=None, graceful_shutdown_timeout=15.0): """Start asynchronous HTTP Server on an individual process. @@ -543,6 +544,16 @@ def serve(host, port, request_handler, error_handler, before_start=None, :param protocol: subclass of asyncio protocol class :param request_class: Request class to use :param access_log: disable/enable access log + :param websocket_max_size: enforces the maximum size for + incoming messages in bytes. + :param websocket_max_queue: sets the maximum length of the queue + that holds incoming messages. + :param websocket_read_limit: sets the high-water limit of the buffer for + incoming bytes, the low-water limit is half + the high-water limit. + :param websocket_write_limit: sets the high-water limit of the buffer for + outgoing bytes, the low-water limit is a + quarter of the high-water limit. :param is_request_stream: disable/enable Request.stream :param router: Router object :return: Nothing @@ -574,6 +585,8 @@ def serve(host, port, request_handler, error_handler, before_start=None, router=router, websocket_max_size=websocket_max_size, websocket_max_queue=websocket_max_queue, + websocket_read_limit=websocket_read_limit, + websocket_write_limit=websocket_write_limit, state=state, debug=debug, )