Skip to content

Commit 65bd931

Browse files
committed
Reintroduce InvalidMessage.
This improves compatibility with the legacy implementation and clarifies error reporting. Fix #1548.
1 parent d8891a1 commit 65bd931

File tree

10 files changed

+32
-20
lines changed

10 files changed

+32
-20
lines changed

docs/reference/exceptions.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ also reported by :func:`~websockets.asyncio.server.serve` in logs.
3030

3131
.. autoexception:: InvalidHandshake
3232

33+
.. autoexception:: InvalidMessage
34+
3335
.. autoexception:: SecurityError
3436

3537
.. autoexception:: InvalidStatus
@@ -74,8 +76,6 @@ Legacy exceptions
7476

7577
These exceptions are only used by the legacy :mod:`asyncio` implementation.
7678

77-
.. autoexception:: InvalidMessage
78-
7979
.. autoexception:: InvalidStatusCode
8080

8181
.. autoexception:: AbortHandshake

src/websockets/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"InvalidHeader",
3232
"InvalidHeaderFormat",
3333
"InvalidHeaderValue",
34+
"InvalidMessage",
3435
"InvalidOrigin",
3536
"InvalidParameterName",
3637
"InvalidParameterValue",
@@ -71,6 +72,7 @@
7172
InvalidHeader,
7273
InvalidHeaderFormat,
7374
InvalidHeaderValue,
75+
InvalidMessage,
7476
InvalidOrigin,
7577
InvalidParameterName,
7678
InvalidParameterValue,
@@ -122,6 +124,7 @@
122124
"InvalidHeader": ".exceptions",
123125
"InvalidHeaderFormat": ".exceptions",
124126
"InvalidHeaderValue": ".exceptions",
127+
"InvalidMessage": ".exceptions",
125128
"InvalidOrigin": ".exceptions",
126129
"InvalidParameterName": ".exceptions",
127130
"InvalidParameterValue": ".exceptions",
@@ -159,7 +162,6 @@
159162
"WebSocketClientProtocol": ".legacy.client",
160163
# .legacy.exceptions
161164
"AbortHandshake": ".legacy.exceptions",
162-
"InvalidMessage": ".legacy.exceptions",
163165
"InvalidStatusCode": ".legacy.exceptions",
164166
"RedirectHandshake": ".legacy.exceptions",
165167
"WebSocketProtocolError": ".legacy.exceptions",

src/websockets/client.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
InvalidHandshake,
1212
InvalidHeader,
1313
InvalidHeaderValue,
14+
InvalidMessage,
1415
InvalidStatus,
1516
InvalidUpgrade,
1617
NegotiationError,
@@ -318,7 +319,10 @@ def parse(self) -> Generator[None]:
318319
self.reader.read_to_eof,
319320
)
320321
except Exception as exc:
321-
self.handshake_exc = exc
322+
self.handshake_exc = InvalidMessage(
323+
"did not receive a valid HTTP response"
324+
)
325+
self.handshake_exc.__cause__ = exc
322326
self.send_eof()
323327
self.parser = self.discard()
324328
next(self.parser) # start coroutine

src/websockets/exceptions.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* :exc:`InvalidURI`
99
* :exc:`InvalidHandshake`
1010
* :exc:`SecurityError`
11-
* :exc:`InvalidMessage` (legacy)
11+
* :exc:`InvalidMessage`
1212
* :exc:`InvalidStatus`
1313
* :exc:`InvalidStatusCode` (legacy)
1414
* :exc:`InvalidHeader`
@@ -48,6 +48,7 @@
4848
"InvalidHeader",
4949
"InvalidHeaderFormat",
5050
"InvalidHeaderValue",
51+
"InvalidMessage",
5152
"InvalidOrigin",
5253
"InvalidUpgrade",
5354
"NegotiationError",
@@ -185,6 +186,13 @@ class SecurityError(InvalidHandshake):
185186
"""
186187

187188

189+
class InvalidMessage(InvalidHandshake):
190+
"""
191+
Raised when a handshake request or response is malformed.
192+
193+
"""
194+
195+
188196
class InvalidStatus(InvalidHandshake):
189197
"""
190198
Raised when a handshake response rejects the WebSocket upgrade.
@@ -410,7 +418,6 @@ class ConcurrencyError(WebSocketException, RuntimeError):
410418
deprecated_aliases={
411419
# deprecated in 14.0 - 2024-11-09
412420
"AbortHandshake": ".legacy.exceptions",
413-
"InvalidMessage": ".legacy.exceptions",
414421
"InvalidStatusCode": ".legacy.exceptions",
415422
"RedirectHandshake": ".legacy.exceptions",
416423
"WebSocketProtocolError": ".legacy.exceptions",

src/websockets/legacy/client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from ..exceptions import (
1818
InvalidHeader,
1919
InvalidHeaderValue,
20+
InvalidMessage,
2021
NegotiationError,
2122
SecurityError,
2223
)
@@ -34,7 +35,7 @@
3435
from ..http11 import USER_AGENT
3536
from ..typing import ExtensionHeader, LoggerLike, Origin, Subprotocol
3637
from ..uri import WebSocketURI, parse_uri
37-
from .exceptions import InvalidMessage, InvalidStatusCode, RedirectHandshake
38+
from .exceptions import InvalidStatusCode, RedirectHandshake
3839
from .handshake import build_request, check_response
3940
from .http import read_response
4041
from .protocol import WebSocketCommonProtocol

src/websockets/legacy/exceptions.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,6 @@
88
from ..typing import StatusLike
99

1010

11-
class InvalidMessage(InvalidHandshake):
12-
"""
13-
Raised when a handshake request or response is malformed.
14-
15-
"""
16-
17-
1811
class InvalidStatusCode(InvalidHandshake):
1912
"""
2013
Raised when a handshake response status code is invalid.

src/websockets/legacy/server.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from ..exceptions import (
1818
InvalidHandshake,
1919
InvalidHeader,
20+
InvalidMessage,
2021
InvalidOrigin,
2122
InvalidUpgrade,
2223
NegotiationError,
@@ -32,7 +33,7 @@
3233
from ..http11 import SERVER
3334
from ..protocol import State
3435
from ..typing import ExtensionHeader, LoggerLike, Origin, StatusLike, Subprotocol
35-
from .exceptions import AbortHandshake, InvalidMessage
36+
from .exceptions import AbortHandshake
3637
from .handshake import build_response, check_request
3738
from .http import read_request
3839
from .protocol import WebSocketCommonProtocol, broadcast

src/websockets/server.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
InvalidHandshake,
1414
InvalidHeader,
1515
InvalidHeaderValue,
16+
InvalidMessage,
1617
InvalidOrigin,
1718
InvalidUpgrade,
1819
NegotiationError,
@@ -552,7 +553,10 @@ def parse(self) -> Generator[None]:
552553
self.reader.read_line,
553554
)
554555
except Exception as exc:
555-
self.handshake_exc = exc
556+
self.handshake_exc = InvalidMessage(
557+
"did not receive a valid HTTP request"
558+
)
559+
self.handshake_exc.__cause__ = exc
556560
self.send_eof()
557561
self.parser = self.discard()
558562
next(self.parser) # start coroutine

tests/legacy/test_exceptions.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77
class ExceptionsTests(unittest.TestCase):
88
def test_str(self):
99
for exception, exception_str in [
10-
(
11-
InvalidMessage("malformed HTTP message"),
12-
"malformed HTTP message",
13-
),
1410
(
1511
InvalidStatusCode(403, Headers()),
1612
"server rejected WebSocket connection: HTTP 403",

tests/test_exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ def test_str(self):
9191
SecurityError("redirect from WSS to WS"),
9292
"redirect from WSS to WS",
9393
),
94+
(
95+
InvalidMessage("malformed HTTP message"),
96+
"malformed HTTP message",
97+
),
9498
(
9599
InvalidStatus(Response(401, "Unauthorized", Headers())),
96100
"server rejected WebSocket connection: HTTP 401",

0 commit comments

Comments
 (0)