1Cheat sheet
2===========
3
4.. currentmodule:: websockets
5
6Server
7------
8
9* Write a coroutine that handles a single connection. It receives a WebSocket
10  protocol instance and the URI path in argument.
11
12  * Call :meth:`~protocol.WebSocketCommonProtocol.recv` and
13    :meth:`~protocol.WebSocketCommonProtocol.send` to receive and send
14    messages at any time.
15
16  * When :meth:`~protocol.WebSocketCommonProtocol.recv` or
17    :meth:`~protocol.WebSocketCommonProtocol.send` raises
18    :exc:`~exceptions.ConnectionClosed`, clean up and exit. If you started
19    other :class:`asyncio.Task`, terminate them before exiting.
20
21  * If you aren't awaiting :meth:`~protocol.WebSocketCommonProtocol.recv`,
22    consider awaiting :meth:`~protocol.WebSocketCommonProtocol.wait_closed`
23    to detect quickly when the connection is closed.
24
25  * You may :meth:`~protocol.WebSocketCommonProtocol.ping` or
26    :meth:`~protocol.WebSocketCommonProtocol.pong` if you wish but it isn't
27    needed in general.
28
29* Create a server with :func:`~server.serve` which is similar to asyncio's
30  :meth:`~asyncio.AbstractEventLoop.create_server`. You can also use it as an
31  asynchronous context manager.
32
33  * The server takes care of establishing connections, then lets the handler
34    execute the application logic, and finally closes the connection after the
35    handler exits normally or with an exception.
36
37  * For advanced customization, you may subclass
38    :class:`~server.WebSocketServerProtocol` and pass either this subclass or
39    a factory function as the ``create_protocol`` argument.
40
41Client
42------
43
44* Create a client with :func:`~client.connect` which is similar to asyncio's
45  :meth:`~asyncio.BaseEventLoop.create_connection`. You can also use it as an
46  asynchronous context manager.
47
48  * For advanced customization, you may subclass
49    :class:`~server.WebSocketClientProtocol` and pass either this subclass or
50    a factory function as the ``create_protocol`` argument.
51
52* Call :meth:`~protocol.WebSocketCommonProtocol.recv` and
53  :meth:`~protocol.WebSocketCommonProtocol.send` to receive and send messages
54  at any time.
55
56* You may :meth:`~protocol.WebSocketCommonProtocol.ping` or
57  :meth:`~protocol.WebSocketCommonProtocol.pong` if you wish but it isn't
58  needed in general.
59
60* If you aren't using :func:`~client.connect` as a context manager, call
61  :meth:`~protocol.WebSocketCommonProtocol.close` to terminate the connection.
62
63.. _debugging:
64
65Debugging
66---------
67
68If you don't understand what ``websockets`` is doing, enable logging::
69
70    import logging
71    logger = logging.getLogger('websockets')
72    logger.setLevel(logging.INFO)
73    logger.addHandler(logging.StreamHandler())
74
75The logs contain:
76
77* Exceptions in the connection handler at the ``ERROR`` level
78* Exceptions in the opening or closing handshake at the ``INFO`` level
79* All frames at the ``DEBUG`` level — this can be very verbose
80
81If you're new to ``asyncio``, you will certainly encounter issues that are
82related to asynchronous programming in general rather than to ``websockets``
83in particular. Fortunately Python's official documentation provides advice to
84`develop with asyncio`_. Check it out: it's invaluable!
85
86.. _develop with asyncio: https://docs.python.org/3/library/asyncio-dev.html
87
88Passing additional arguments to the connection handler
89------------------------------------------------------
90
91When writing a server, if you need to pass additional arguments to the
92connection handler, you can bind them with :func:`functools.partial`::
93
94    import asyncio
95    import functools
96    import websockets
97
98    async def handler(websocket, path, extra_argument):
99        ...
100
101    bound_handler = functools.partial(handler, extra_argument='spam')
102    start_server = websockets.serve(bound_handler, '127.0.0.1', 8765)
103
104    asyncio.get_event_loop().run_until_complete(start_server)
105    asyncio.get_event_loop().run_forever()
106
107Another way to achieve this result is to define the ``handler`` coroutine in
108a scope where the ``extra_argument`` variable exists instead of injecting it
109through an argument.
110