Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/websockets/exceptions.py: 50%
112 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:20 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:20 +0000
1"""
2:mod:`websockets.exceptions` defines the following exception hierarchy:
4* :exc:`WebSocketException`
5 * :exc:`ConnectionClosed`
6 * :exc:`ConnectionClosedError`
7 * :exc:`ConnectionClosedOK`
8 * :exc:`InvalidHandshake`
9 * :exc:`SecurityError`
10 * :exc:`InvalidMessage`
11 * :exc:`InvalidHeader`
12 * :exc:`InvalidHeaderFormat`
13 * :exc:`InvalidHeaderValue`
14 * :exc:`InvalidOrigin`
15 * :exc:`InvalidUpgrade`
16 * :exc:`InvalidStatus`
17 * :exc:`InvalidStatusCode` (legacy)
18 * :exc:`NegotiationError`
19 * :exc:`DuplicateParameter`
20 * :exc:`InvalidParameterName`
21 * :exc:`InvalidParameterValue`
22 * :exc:`AbortHandshake`
23 * :exc:`RedirectHandshake`
24 * :exc:`InvalidState`
25 * :exc:`InvalidURI`
26 * :exc:`PayloadTooBig`
27 * :exc:`ProtocolError`
29"""
31from __future__ import annotations
33import http
34from typing import Optional
36from . import datastructures, frames, http11
39__all__ = [
40 "WebSocketException",
41 "ConnectionClosed",
42 "ConnectionClosedError",
43 "ConnectionClosedOK",
44 "InvalidHandshake",
45 "SecurityError",
46 "InvalidMessage",
47 "InvalidHeader",
48 "InvalidHeaderFormat",
49 "InvalidHeaderValue",
50 "InvalidOrigin",
51 "InvalidUpgrade",
52 "InvalidStatus",
53 "InvalidStatusCode",
54 "NegotiationError",
55 "DuplicateParameter",
56 "InvalidParameterName",
57 "InvalidParameterValue",
58 "AbortHandshake",
59 "RedirectHandshake",
60 "InvalidState",
61 "InvalidURI",
62 "PayloadTooBig",
63 "ProtocolError",
64 "WebSocketProtocolError",
65]
68class WebSocketException(Exception):
69 """
70 Base class for all exceptions defined by websockets.
72 """
75class ConnectionClosed(WebSocketException):
76 """
77 Raised when trying to interact with a closed connection.
79 Attributes:
80 rcvd (Optional[Close]): if a close frame was received, its code and
81 reason are available in ``rcvd.code`` and ``rcvd.reason``.
82 sent (Optional[Close]): if a close frame was sent, its code and reason
83 are available in ``sent.code`` and ``sent.reason``.
84 rcvd_then_sent (Optional[bool]): if close frames were received and
85 sent, this attribute tells in which order this happened, from the
86 perspective of this side of the connection.
88 """
90 def __init__(
91 self,
92 rcvd: Optional[frames.Close],
93 sent: Optional[frames.Close],
94 rcvd_then_sent: Optional[bool] = None,
95 ) -> None:
96 self.rcvd = rcvd
97 self.sent = sent
98 self.rcvd_then_sent = rcvd_then_sent
100 def __str__(self) -> str:
101 if self.rcvd is None:
102 if self.sent is None:
103 assert self.rcvd_then_sent is None
104 return "no close frame received or sent"
105 else:
106 assert self.rcvd_then_sent is None
107 return f"sent {self.sent}; no close frame received"
108 else:
109 if self.sent is None:
110 assert self.rcvd_then_sent is None
111 return f"received {self.rcvd}; no close frame sent"
112 else:
113 assert self.rcvd_then_sent is not None
114 if self.rcvd_then_sent:
115 return f"received {self.rcvd}; then sent {self.sent}"
116 else:
117 return f"sent {self.sent}; then received {self.rcvd}"
119 # code and reason attributes are provided for backwards-compatibility
121 @property
122 def code(self) -> int:
123 if self.rcvd is None:
124 return frames.CloseCode.ABNORMAL_CLOSURE
125 return self.rcvd.code
127 @property
128 def reason(self) -> str:
129 if self.rcvd is None:
130 return ""
131 return self.rcvd.reason
134class ConnectionClosedError(ConnectionClosed):
135 """
136 Like :exc:`ConnectionClosed`, when the connection terminated with an error.
138 A close frame with a code other than 1000 (OK) or 1001 (going away) was
139 received or sent, or the closing handshake didn't complete properly.
141 """
144class ConnectionClosedOK(ConnectionClosed):
145 """
146 Like :exc:`ConnectionClosed`, when the connection terminated properly.
148 A close code with code 1000 (OK) or 1001 (going away) or without a code was
149 received and sent.
151 """
154class InvalidHandshake(WebSocketException):
155 """
156 Raised during the handshake when the WebSocket connection fails.
158 """
161class SecurityError(InvalidHandshake):
162 """
163 Raised when a handshake request or response breaks a security rule.
165 Security limits are hard coded.
167 """
170class InvalidMessage(InvalidHandshake):
171 """
172 Raised when a handshake request or response is malformed.
174 """
177class InvalidHeader(InvalidHandshake):
178 """
179 Raised when an HTTP header doesn't have a valid format or value.
181 """
183 def __init__(self, name: str, value: Optional[str] = None) -> None:
184 self.name = name
185 self.value = value
187 def __str__(self) -> str:
188 if self.value is None:
189 return f"missing {self.name} header"
190 elif self.value == "":
191 return f"empty {self.name} header"
192 else:
193 return f"invalid {self.name} header: {self.value}"
196class InvalidHeaderFormat(InvalidHeader):
197 """
198 Raised when an HTTP header cannot be parsed.
200 The format of the header doesn't match the grammar for that header.
202 """
204 def __init__(self, name: str, error: str, header: str, pos: int) -> None:
205 super().__init__(name, f"{error} at {pos} in {header}")
208class InvalidHeaderValue(InvalidHeader):
209 """
210 Raised when an HTTP header has a wrong value.
212 The format of the header is correct but a value isn't acceptable.
214 """
217class InvalidOrigin(InvalidHeader):
218 """
219 Raised when the Origin header in a request isn't allowed.
221 """
223 def __init__(self, origin: Optional[str]) -> None:
224 super().__init__("Origin", origin)
227class InvalidUpgrade(InvalidHeader):
228 """
229 Raised when the Upgrade or Connection header isn't correct.
231 """
234class InvalidStatus(InvalidHandshake):
235 """
236 Raised when a handshake response rejects the WebSocket upgrade.
238 """
240 def __init__(self, response: http11.Response) -> None:
241 self.response = response
243 def __str__(self) -> str:
244 return (
245 "server rejected WebSocket connection: "
246 f"HTTP {self.response.status_code:d}"
247 )
250class InvalidStatusCode(InvalidHandshake):
251 """
252 Raised when a handshake response status code is invalid.
254 """
256 def __init__(self, status_code: int, headers: datastructures.Headers) -> None:
257 self.status_code = status_code
258 self.headers = headers
260 def __str__(self) -> str:
261 return f"server rejected WebSocket connection: HTTP {self.status_code}"
264class NegotiationError(InvalidHandshake):
265 """
266 Raised when negotiating an extension fails.
268 """
271class DuplicateParameter(NegotiationError):
272 """
273 Raised when a parameter name is repeated in an extension header.
275 """
277 def __init__(self, name: str) -> None:
278 self.name = name
280 def __str__(self) -> str:
281 return f"duplicate parameter: {self.name}"
284class InvalidParameterName(NegotiationError):
285 """
286 Raised when a parameter name in an extension header is invalid.
288 """
290 def __init__(self, name: str) -> None:
291 self.name = name
293 def __str__(self) -> str:
294 return f"invalid parameter name: {self.name}"
297class InvalidParameterValue(NegotiationError):
298 """
299 Raised when a parameter value in an extension header is invalid.
301 """
303 def __init__(self, name: str, value: Optional[str]) -> None:
304 self.name = name
305 self.value = value
307 def __str__(self) -> str:
308 if self.value is None:
309 return f"missing value for parameter {self.name}"
310 elif self.value == "":
311 return f"empty value for parameter {self.name}"
312 else:
313 return f"invalid value for parameter {self.name}: {self.value}"
316class AbortHandshake(InvalidHandshake):
317 """
318 Raised to abort the handshake on purpose and return an HTTP response.
320 This exception is an implementation detail.
322 The public API
323 is :meth:`~websockets.server.WebSocketServerProtocol.process_request`.
325 Attributes:
326 status (~http.HTTPStatus): HTTP status code.
327 headers (Headers): HTTP response headers.
328 body (bytes): HTTP response body.
329 """
331 def __init__(
332 self,
333 status: http.HTTPStatus,
334 headers: datastructures.HeadersLike,
335 body: bytes = b"",
336 ) -> None:
337 # If a user passes an int instead of a HTTPStatus, fix it automatically.
338 self.status = http.HTTPStatus(status)
339 self.headers = datastructures.Headers(headers)
340 self.body = body
342 def __str__(self) -> str:
343 return (
344 f"HTTP {self.status:d}, "
345 f"{len(self.headers)} headers, "
346 f"{len(self.body)} bytes"
347 )
350class RedirectHandshake(InvalidHandshake):
351 """
352 Raised when a handshake gets redirected.
354 This exception is an implementation detail.
356 """
358 def __init__(self, uri: str) -> None:
359 self.uri = uri
361 def __str__(self) -> str:
362 return f"redirect to {self.uri}"
365class InvalidState(WebSocketException, AssertionError):
366 """
367 Raised when an operation is forbidden in the current state.
369 This exception is an implementation detail.
371 It should never be raised in normal circumstances.
373 """
376class InvalidURI(WebSocketException):
377 """
378 Raised when connecting to a URI that isn't a valid WebSocket URI.
380 """
382 def __init__(self, uri: str, msg: str) -> None:
383 self.uri = uri
384 self.msg = msg
386 def __str__(self) -> str:
387 return f"{self.uri} isn't a valid URI: {self.msg}"
390class PayloadTooBig(WebSocketException):
391 """
392 Raised when receiving a frame with a payload exceeding the maximum size.
394 """
397class ProtocolError(WebSocketException):
398 """
399 Raised when a frame breaks the protocol.
401 """
404WebSocketProtocolError = ProtocolError # for backwards compatibility