Changelog¶
8.2¶
In development
8.1¶
Added compatibility with Python 3.8.
8.0.2¶
Restored the ability to pass a socket with the
sockparameter ofserve().Removed an incorrect assertion when a connection drops.
8.0.1¶
Restored the ability to import
WebSocketProtocolErrorfromwebsockets.
8.0¶
Warning
Version 8.0 drops compatibility with Python 3.4 and 3.5.
Note
Version 8.0 expects process_request to be a coroutine.
Previously, it could be a function or a coroutine.
If you’re passing a process_request argument to serve()
or WebSocketServerProtocol, or if you’re overriding
process_request() in a subclass,
define it with async def instead of def.
For backwards compatibility, functions are still mostly supported, but mixing functions and coroutines won’t work in some inheritance scenarios.
Note
Version 8.0 changes the behavior of the max_queue parameter.
If you were setting max_queue=0 to make the queue of incoming messages
unbounded, change it to max_queue=None.
Note
Version 8.0 deprecates the host , port , and secure
attributes of WebSocketCommonProtocol.
Use local_address in servers and
remote_address in clients
instead of host and port.
Note
Version 8.0 renames the WebSocketProtocolError exception
to ProtocolError .
A WebSocketProtocolError alias provides backwards compatibility.
Note
Version 8.0 adds the reason phrase to the return type of the low-level
API read_response() .
Also:
send(),ping(), andpong()support bytes-like typesbytearrayandmemoryviewin addition tobytes.Added
ConnectionClosedOKandConnectionClosedErrorsubclasses ofConnectionClosedto tell apart normal connection termination from errors.Added
basic_auth_protocol_factory()to enforce HTTP Basic Auth on the server side.connect()handles redirects from the server during the handshake.connect()supports overridinghostandport.Added
unix_connect()for connecting to Unix sockets.Improved support for sending fragmented messages by accepting asynchronous iterators in
send().Prevented spurious log messages about
ConnectionClosedexceptions in keepalive ping task. If you were usingping_timeout=Noneas a workaround, you can remove it.Changed
WebSocketServer.close()to perform a proper closing handshake instead of failing the connection.Avoided a crash when a
extra_headerscallable returnsNone.Improved error messages when HTTP parsing fails.
Enabled readline in the interactive client.
Added type hints (PEP 484).
Added a FAQ to the documentation.
Added documentation for extensions.
Documented how to optimize memory usage.
Improved API documentation.
7.0¶
Warning
Version 7.0 renames the timeout argument of
serve() and connect() to
close_timeout .
This prevents confusion with ping_timeout.
For backwards compatibility, timeout is still supported.
Warning
Version 7.0 changes how a server terminates connections when it’s
closed with close() .
Previously, connections handlers were canceled. Now, connections are
closed with close code 1001 (going away). From the perspective of the
connection handler, this is the same as if the remote endpoint was
disconnecting. This removes the need to prepare for
CancelledError in connection handlers.
You can restore the previous behavior by adding the following line at the beginning of connection handlers:
def handler(websocket, path):
closed = asyncio.ensure_future(websocket.wait_closed())
closed.add_done_callback(lambda task: task.cancel())
Note
Version 7.0 changes how a ping()
that hasn’t received a pong yet behaves when the connection is closed.
The ping — as in ping = await websocket.ping() — used to be canceled
when the connection is closed, so that await ping raised
CancelledError. Now await ping raises
ConnectionClosed like other public APIs.
Note
Version 7.0 raises a RuntimeError exception if two coroutines
call recv() concurrently.
Concurrent calls lead to non-deterministic behavior because there are no guarantees about which coroutine will receive which message.
Also:
websocketssends Ping frames at regular intervals and closes the connection if it doesn’t receive a matching Pong frame. SeeWebSocketCommonProtocolfor details.Added
process_requestandselect_subprotocolarguments toserve()andWebSocketServerProtocolto customizeprocess_request()andselect_subprotocol()without subclassingWebSocketServerProtocol.Added support for sending fragmented messages.
Added the
wait_closed()method to protocols.Added an interactive client:
python -m websockets <uri>.Changed the
originsargument to represent the lack of an origin withNonerather than''.Fixed a data loss bug in
recv(): canceling it at the wrong time could result in messages being dropped.Improved handling of multiple HTTP headers with the same name.
Improved error messages when a required HTTP header is missing.
6.0¶
Warning
Version 6.0 introduces the Headers class for managing
HTTP headers and changes several public APIs:
process_request()now receives aHeadersinstead of aHTTPMessagein therequest_headersargument.The
request_headersandresponse_headersattributes ofWebSocketCommonProtocolareHeadersinstead ofHTTPMessage.The
raw_request_headersandraw_response_headersattributes ofWebSocketCommonProtocolare removed. Useraw_items()instead.Functions defined in the
handshakemodule now receiveHeadersin argument instead ofget_headerorset_headerfunctions. This affects libraries that rely on low-level APIs.Functions defined in the
httpmodule now return HTTP headers asHeadersinstead of lists of(name, value)pairs.
Since Headers and HTTPMessage provide
similar APIs, this change won’t affect most of the code dealing with HTTP
headers.
Also:
Added compatibility with Python 3.7.
5.0.1¶
5.0¶
Note
Version 5.0 fixes a security issue introduced in version 4.0.
Version 4.0 was vulnerable to denial of service by memory exhaustion
because it didn’t enforce max_size when decompressing compressed
messages (CVE-2018-1000518).
Note
Version 5.0 adds a user_info field to the return value of
parse_uri() and WebSocketURI .
If you’re unpacking WebSocketURI into four variables,
adjust your code to account for that fifth field.
Also:
connect()performs HTTP Basic Auth when the URI contains credentials.Iterating on incoming messages no longer raises an exception when the connection terminates with close code 1001 (going away).
A plain HTTP request now receives a 426 Upgrade Required response and doesn’t log a stack trace.
unix_serve()can be used as an asynchronous context manager on Python ≥ 3.5.1.Added the
closedproperty to protocols.If a
ping()doesn’t receive a pong, it’s canceled when the connection is closed.Reported the cause of
ConnectionClosedexceptions.Added new examples in the documentation.
Updated documentation with new features from Python 3.6.
Improved several other sections of the documentation.
Fixed missing close code, which caused
TypeErroron connection close.Fixed a race condition in the closing handshake that raised
InvalidState.Stopped logging stack traces when the TCP connection dies prematurely.
Prevented writing to a closing TCP connection during unclean shutdowns.
Made connection termination more robust to network congestion.
Prevented processing of incoming frames after failing the connection.
4.0.1¶
Fixed issues with the packaging of the 4.0 release.
4.0¶
Warning
Version 4.0 enables compression with the permessage-deflate extension.
In August 2017, Firefox and Chrome support it, but not Safari and IE.
Compression should improve performance but it increases RAM and CPU use.
If you want to disable compression, add compression=None when calling
serve() or connect().
Warning
Version 4.0 drops compatibility with Python 3.3.
Note
Version 4.0 removes the state_name attribute of protocols.
Use protocol.state.name instead of protocol.state_name.
Also:
WebSocketCommonProtocolinstances can be used as asynchronous iterators on Python ≥ 3.6. They yield incoming messages.Added
unix_serve()for listening on Unix sockets.Reorganized and extended documentation.
Aborted connections if they don’t close within the configured
timeout.Rewrote connection termination to increase robustness in edge cases.
Stopped leaking pending tasks when
cancel()is called on a connection while it’s being closed.Reduced verbosity of “Failing the WebSocket connection” logs.
Allowed
extra_headersto overrideServerandUser-Agentheaders.
3.4¶
Renamed
serve()andconnect()’sklassargument tocreate_protocolto reflect that it can also be a callable. For backwards compatibility,klassis still supported.serve()can be used as an asynchronous context manager on Python ≥ 3.5.1.Added support for customizing handling of incoming connections with
process_request().Made read and write buffer sizes configurable.
Rewrote HTTP handling for simplicity and performance.
Added an optional C extension to speed up low-level operations.
An invalid response status code during
connect()now raisesInvalidStatusCodewith acodeattribute.Providing a
sockargument toconnect()no longer crashes.
3.3¶
Ensured compatibility with Python 3.6.
Reduced noise in logs caused by connection resets.
Avoided crashing on concurrent writes on slow connections.
3.2¶
3.1¶
Avoided a warning when closing a connection before the opening handshake.
Added flow control for incoming data.
3.0¶
Warning
Version 3.0 introduces a backwards-incompatible change in the
recv() API.
If you’re upgrading from 2.x or earlier, please read this carefully.
recv() used to return None
when the connection was closed. This required checking the return value of
every call:
message = await websocket.recv()
if message is None:
return
Now it raises a ConnectionClosed exception instead.
This is more Pythonic. The previous code can be simplified to:
message = await websocket.recv()
When implementing a server, which is the more popular use case, there’s no strong reason to handle such exceptions. Let them bubble up, terminate the handler coroutine, and the server will simply ignore them.
In order to avoid stranding projects built upon an earlier version, the
previous behavior can be restored by passing legacy_recv=True to
serve(), connect(),
WebSocketServerProtocol, or
WebSocketClientProtocol. legacy_recv isn’t documented
in their signatures but isn’t scheduled for deprecation either.
Also:
connect()can be used as an asynchronous context manager on Python ≥ 3.5.1.Updated documentation with
awaitandasyncsyntax from Python 3.5.ping()andpong()support data passed asstrin addition tobytes.Worked around an asyncio bug affecting connection termination under load.
Made
state_nameattribute on protocols a public API.Improved documentation.
2.7¶
Added compatibility with Python 3.5.
Refreshed documentation.
2.6¶
Added
local_addressandremote_addressattributes on protocols.Closed open connections with code 1001 when a server shuts down.
Avoided TCP fragmentation of small frames.
2.5¶
Improved documentation.
Provided access to handshake request and response HTTP headers.
Allowed customizing handshake request and response HTTP headers.
Supported running on a non-default event loop.
Returned a 403 status code instead of 400 when the request Origin isn’t allowed.
Canceling
recv()no longer drops the next message.Clarified that the closing handshake can be initiated by the client.
Set the close code and reason more consistently.
Strengthened connection termination by simplifying the implementation.
Improved tests, added tox configuration, and enforced 100% branch coverage.
2.4¶
2.3¶
Improved compliance of close codes.
2.2¶
Added support for limiting message size.
2.1¶
Added
host,portandsecureattributes on protocols.Added support for providing and checking Origin.
2.0¶
Warning
Version 2.0 introduces a backwards-incompatible change in the
send(),
ping(), and
pong() APIs.
If you’re upgrading from 1.x or earlier, please read this carefully.
These APIs used to be functions. Now they’re coroutines.
Instead of:
websocket.send(message)
you must now write:
await websocket.send(message)
Also:
Added flow control for outgoing data.
1.0¶
Initial public release.