Server¶
Starting a server¶
- await websockets.server.serve(ws_handler, host=None, port=None, *, create_protocol=None, ping_interval=20, ping_timeout=20, close_timeout=None, max_size=1048576, max_queue=32, read_limit=65536, write_limit=65536, loop=None, compression='deflate', origins=None, extensions=None, subprotocols=None, extra_headers=None, process_request=None, select_subprotocol=None, **kwargs)¶
Create, start, and return a WebSocket server on
host
andport
.Whenever a client connects, the server accepts the connection, creates a
WebSocketServerProtocol
, performs the opening handshake, and delegates to the connection handler defined byws_handler
. Once the handler completes, either normally or with an exception, the server performs the closing handshake and closes the connection.Awaiting
serve()
yields aWebSocketServer
. This instance providesclose()
andwait_closed()
methods for terminating the server and cleaning up its resources.When a server is closed with
close()
, it closes all connections with close code 1001 (going away). Connections handlers, which are running thews_handler
coroutine, will receive aConnectionClosedOK
exception on their current or next interaction with the WebSocket connection.serve()
can also be used as an asynchronous context manager:stop = asyncio.Future() # set this future to exit the server async with serve(...): await stop
In this case, the server is shut down when exiting the context.
serve()
is a wrapper around the event loop’screate_server()
method. It creates and starts aasyncio.Server
withcreate_server()
. Then it wraps theasyncio.Server
in aWebSocketServer
and returns theWebSocketServer
.ws_handler
is the WebSocket handler. It must be a coroutine accepting two arguments: the WebSocket connection, which is an instance ofWebSocketServerProtocol
, and the path of the request.The
host
andport
arguments, as well as unrecognized keyword arguments, are passed tocreate_server()
.For example, you can set the
ssl
keyword argument to aSSLContext
to enable TLS.create_protocol
defaults toWebSocketServerProtocol
. It may be replaced by a wrapper or a subclass to customize the protocol that manages the connection.The behavior of
ping_interval
,ping_timeout
,close_timeout
,max_size
,max_queue
,read_limit
, andwrite_limit
is described inWebSocketServerProtocol
.serve()
also accepts the following optional arguments:compression
is a shortcut to configure compression extensions; by default it enables the “permessage-deflate” extension; set it toNone
to disable compression.origins
defines acceptable Origin HTTP headers; includeNone
in the list if the lack of an origin is acceptable.extensions
is a list of supported extensions in order of decreasing preference.subprotocols
is a list of supported subprotocols in order of decreasing preference.extra_headers
sets additional HTTP response headers when the handshake succeeds; it can be aHeaders
instance, aMapping
, an iterable of(name, value)
pairs, or a callable taking the request path and headers in arguments and returning one of the above.process_request
allows intercepting the HTTP request; it must be a coroutine taking the request path and headers in argument; seeprocess_request()
for details.select_subprotocol
allows customizing the logic for selecting a subprotocol; it must be a callable taking the subprotocols offered by the client and available on the server in argument; seeselect_subprotocol()
for details.
Since there’s no useful way to propagate exceptions triggered in handlers, they’re sent to the
"websockets.server"
logger instead. Debugging is much easier if you configure logging to print them:import logging logger = logging.getLogger("websockets.server") logger.setLevel(logging.ERROR) logger.addHandler(logging.StreamHandler())
- await websockets.server.unix_serve(ws_handler, path=None, **kwargs)[source]¶
Similar to
serve()
, but for listening on Unix sockets.This function calls the event loop’s
create_unix_server()
method.It is only available on Unix.
It’s useful for deploying a server behind a reverse proxy such as nginx.
Stopping a server¶
- class websockets.server.WebSocketServer(loop)[source]¶
WebSocket server returned by
serve()
.This class provides the same interface as
AbstractServer
, namely theclose()
andwait_closed()
methods.It keeps track of WebSocket connections in order to close them properly when shutting down.
Instances of this class store a reference to the
Server
object returned bycreate_server()
rather than inherit fromServer
in part becausecreate_server()
doesn’t support passing a customServer
class.- close()[source]¶
Close the server.
This method: :rtype:
None
closes the underlying
Server
;rejects new WebSocket connections with an HTTP 503 (service unavailable) error; this happens when the server accepted the TCP connection but didn’t complete the WebSocket opening handshake prior to closing;
closes open WebSocket connections with close code 1001 (going away).
close()
is idempotent.
- await wait_closed()[source]¶
Wait until the server is closed.
When
wait_closed()
returns, all TCP connections are closed and all connection handlers have returned.- Return type:
Using a connection¶
- class websockets.server.WebSocketServerProtocol(ws_handler, ws_server, *, origins=None, extensions=None, subprotocols=None, extra_headers=None, process_request=None, select_subprotocol=None, **kwargs)[source]¶
Protocol
subclass implementing a WebSocket server.performs the opening handshake to establish the connection;
provides
recv()
andsend()
coroutines for receiving and sending messages;deals with control frames automatically;
performs the closing handshake to terminate the connection.
You may customize the opening handshake by subclassing
WebSocketServer
and overriding:process_request()
to intercept the client request before any processing and, if appropriate, to abort the WebSocket request and return a HTTP response instead;select_subprotocol()
to select a subprotocol, if the client and the server have multiple subprotocols in common and the default logic for choosing one isn’t suitable (this is rarely needed).
WebSocketServerProtocol
supports asynchronous iteration:async for message in websocket: await process(message)
The iterator yields incoming messages. It exits normally when the connection is closed with the close code 1000 (OK) or 1001 (going away). It raises a
ConnectionClosedError
exception when the connection is closed with any other code.Once the connection is open, a Ping frame is sent every
ping_interval
seconds. This serves as a keepalive. It helps keeping the connection open, especially in the presence of proxies with short timeouts on inactive connections. Setping_interval
toNone
to disable this behavior.If the corresponding Pong frame isn’t received within
ping_timeout
seconds, the connection is considered unusable and is closed with code 1011. This ensures that the remote endpoint remains responsive. Setping_timeout
toNone
to disable this behavior.The
close_timeout
parameter defines a maximum wait time for completing the closing handshake and terminating the TCP connection. For legacy reasons,close()
completes in at most4 * close_timeout
seconds.close_timeout
needs to be a parameter of the protocol because websockets usually callsclose()
implicitly when the connection handler terminates.To apply a timeout to any other API, wrap it in
wait_for()
.The
max_size
parameter enforces the maximum size for incoming messages in bytes. The default value is 1 MiB.None
disables the limit. If a message larger than the maximum size is received,recv()
will raiseConnectionClosedError
and the connection will be closed with code 1009.The
max_queue
parameter sets the maximum length of the queue that holds incoming messages. The default value is32
.None
disables the limit. Messages are added to an in-memory queue when they’re received; thenrecv()
pops from that queue. In order to prevent excessive memory consumption when messages are received faster than they can be processed, the queue must be bounded. If the queue fills up, the protocol stops processing incoming data untilrecv()
is called. In this situation, various receive buffers (at least inasyncio
and in the OS) will fill up, then the TCP receive window will shrink, slowing down transmission to avoid packet loss.Since Python can use up to 4 bytes of memory to represent a single character, each connection may use up to
4 * max_size * max_queue
bytes of memory to store incoming messages. By default, this is 128 MiB. You may want to lower the limits, depending on your application’s requirements.The
read_limit
argument sets the high-water limit of the buffer for incoming bytes. The low-water limit is half the high-water limit. The default value is 64 KiB, half of asyncio’s default (based on the current implementation ofStreamReader
).The
write_limit
argument sets the high-water limit of the buffer for outgoing bytes. The low-water limit is a quarter of the high-water limit. The default value is 64 KiB, equal to asyncio’s default (based on the current implementation ofFlowControlMixin
).As soon as the HTTP request and response in the opening handshake are processed:
the request path is available in the
path
attribute;the request and response HTTP headers are available in the
request_headers
andresponse_headers
attributes, which areHeaders
instances.
If a subprotocol was negotiated, it’s available in the
subprotocol
attribute.Once the connection is closed, the code is available in the
close_code
attribute and the reason inclose_reason
.All attributes must be treated as read-only.
- local_address¶
Local address of the connection as a
(host, port)
tuple.When the connection isn’t open,
local_address
isNone
.
- remote_address¶
Remote address of the connection as a
(host, port)
tuple.When the connection isn’t open,
remote_address
isNone
.
- open¶
True
when the connection is usable.It may be used to detect disconnections. However, this approach is discouraged per the EAFP principle.
When
open
isFalse
, using the connection raises aConnectionClosed
exception.
- closed¶
True
once the connection is closed.Be aware that both
open
andclosed
areFalse
during the opening and closing sequences.
- path¶
Path of the HTTP request.
Available once the connection is open.
- request_headers¶
HTTP request headers as a
Headers
instance.Available once the connection is open.
- response_headers¶
HTTP response headers as a
Headers
instance.Available once the connection is open.
- subprotocol¶
Subprotocol, if one was negotiated.
Available once the connection is open.
- close_code¶
WebSocket close code.
Available once the connection is closed.
- close_reason¶
WebSocket close reason.
Available once the connection is closed.
- await process_request(path, request_headers)[source]¶
Intercept the HTTP request and return an HTTP response if appropriate.
If
process_request
returnsNone
, the WebSocket handshake continues. If it returns 3-uple containing a status code, response headers and a response body, that HTTP response is sent and the connection is closed. In that case:The HTTP status must be a
HTTPStatus
.HTTP headers must be a
Headers
instance, aMapping
, or an iterable of(name, value)
pairs.The HTTP response body must be
bytes
. It may be empty.
This coroutine may be overridden in a
WebSocketServerProtocol
subclass, for example:to return a HTTP 200 OK response on a given path; then a load balancer can use this path for a health check;
to authenticate the request and return a HTTP 401 Unauthorized or a HTTP 403 Forbidden when authentication fails.
Instead of subclassing, it is possible to override this method by passing a
process_request
argument to theserve()
function or theWebSocketServerProtocol
constructor. This is equivalent, exceptprocess_request
won’t have access to the protocol instance, so it can’t store information for later use.process_request
is expected to complete quickly. If it may run for a long time, then it should awaitwait_closed()
and exit ifwait_closed()
completes, or else it could prevent the server from shutting down.
- select_subprotocol(client_subprotocols, server_subprotocols)[source]¶
Pick a subprotocol among those offered by the client.
If several subprotocols are supported by the client and the server, the default implementation selects the preferred subprotocols by giving equal value to the priorities of the client and the server.
If no subprotocol is supported by the client and the server, it proceeds without a subprotocol.
This is unlikely to be the most useful implementation in practice, as many servers providing a subprotocol will require that the client uses that subprotocol. Such rules can be implemented in a subclass.
Instead of subclassing, it is possible to override this method by passing a
select_subprotocol
argument to theserve()
function or theWebSocketServerProtocol
constructor.
- await recv()¶
Receive the next message.
Return a
str
for a text frame andbytes
for a binary frame.When the end of the message stream is reached,
recv()
raisesConnectionClosed
. Specifically, it raisesConnectionClosedOK
after a normal connection closure andConnectionClosedError
after a protocol error or a network failure.Canceling
recv()
is safe. There’s no risk of losing the next message. The next invocation ofrecv()
will return it. This makes it possible to enforce a timeout by wrappingrecv()
inwait_for()
.- Raises:
ConnectionClosed – when the connection is closed
RuntimeError – if two coroutines call
recv()
concurrently
- Return type:
- await send(message)¶
Send a message.
A string (
str
) is sent as a Text frame. A bytestring or bytes-like object (bytes
,bytearray
, ormemoryview
) is sent as a Binary frame. :rtype:None
send()
also accepts an iterable or an asynchronous iterable of strings, bytestrings, or bytes-like objects. In that case the message is fragmented. Each item is treated as a message fragment and sent in its own frame. All items must be of the same type, or elsesend()
will raise aTypeError
and the connection will be closed.send()
rejects dict-like objects because this is often an error. If you wish to send the keys of a dict-like object as fragments, call itskeys()
method and pass the result tosend()
.Canceling
send()
is discouraged. Instead, you should close the connection withclose()
. Indeed, there are only two situations wheresend()
may yield control to the event loop:The write buffer is full. If you don’t want to wait until enough data is sent, your only alternative is to close the connection.
close()
will likely time out then abort the TCP connection.message
is an asynchronous iterator that yields control. Stopping in the middle of a fragmented message will cause a protocol error. Closing the connection has the same effect.
- Raises:
TypeError – for unsupported inputs
- await ping(data=None)¶
Send a ping.
Return a
Future
that will be completed when the corresponding pong is received. You can ignore it if you don’t intend to wait.A ping may serve as a keepalive or as a check that the remote endpoint received all messages up to this point:
pong_waiter = await ws.ping() await pong_waiter # only if you want to wait for the pong
By default, the ping contains four random bytes. This payload may be overridden with the optional
data
argument which must be a string (which will be encoded to UTF-8) or a bytes-like object.Canceling
ping()
is discouraged. Ifping()
doesn’t return immediately, it means the write buffer is full. If you don’t want to wait, you should close the connection.
- await pong(data=b'')¶
Send a pong.
An unsolicited pong may serve as a unidirectional heartbeat.
The payload may be set with the optional
data
argument which must be a string (which will be encoded to UTF-8) or a bytes-like object.Canceling
pong()
is discouraged for the same reason asping()
.- Return type:
- await close(code=1000, reason='')¶
Perform the closing handshake.
close()
waits for the other end to complete the handshake and for the TCP connection to terminate. As a consequence, there’s no need to awaitwait_closed()
;close()
already does it.close()
is idempotent: it doesn’t do anything once the connection is closed.Wrapping
close()
increate_task()
is safe, given that errors during connection termination aren’t particularly useful.Canceling
close()
is discouraged. If it takes too long, you can set a shorterclose_timeout
. If you don’t want to wait, let the Python process exit, then the OS will close the TCP connection.
Basic authentication¶
- websockets.auth.basic_auth_protocol_factory(realm, credentials=None, check_credentials=None, create_protocol=None)[source]¶
Protocol factory that enforces HTTP Basic Auth.
basic_auth_protocol_factory
is designed to integrate withserve()
like this:websockets.serve( ..., create_protocol=websockets.basic_auth_protocol_factory( realm="my dev server", credentials=("hello", "iloveyou"), ) )
realm
indicates the scope of protection. It should contain only ASCII characters because the encoding of non-ASCII characters is undefined. Refer to section 2.2 of RFC 7235 for details.credentials
defines hard coded authorized credentials. It can be a(username, password)
pair or a list of such pairs.check_credentials
defines a coroutine that checks whether credentials are authorized. This coroutine receivesusername
andpassword
arguments and returns abool
.One of
credentials
orcheck_credentials
must be provided but not both.By default,
basic_auth_protocol_factory
creates a factory for buildingBasicAuthWebSocketServerProtocol
instances. You can override this with thecreate_protocol
parameter.- Parameters:
- Raises:
TypeError – if the credentials argument has the wrong type
- Return type:
- class websockets.auth.BasicAuthWebSocketServerProtocol(*args, realm, check_credentials, **kwargs)[source]¶
WebSocket server protocol that enforces HTTP Basic Auth.
- await process_request(path, request_headers)[source]¶
Check HTTP Basic Auth and return a HTTP 401 or 403 response if needed.
- username¶
Username of the authenticated user.