Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/project/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ New features
* Added the ``--insecure`` option to the ``websockets`` CLI to disable TLS
certificate validation.

Bug fixes
.........

* Avoided an internal assertion when the :mod:`threading` server rejects an
opening handshake. (:issue:`1722`)

.. _16.1:

16.1
Expand Down
5 changes: 4 additions & 1 deletion src/websockets/sync/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,10 @@ def protocol_select_subprotocol(
connection.recv_events_thread.join()
return

assert connection.protocol.state is OPEN
if connection.protocol.state is not OPEN:
connection.close_socket()
connection.recv_events_thread.join()
return
try:
connection.start_keepalive()
handler(connection)
Expand Down
34 changes: 26 additions & 8 deletions tests/sync/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import http
import logging
import socket
import threading
import time
import unittest

Expand Down Expand Up @@ -145,20 +146,37 @@ def process_request(ws, request):
def test_process_request_returns_response(self):
"""Server aborts handshake if process_request returns a response."""

assertions = []

def trace(frame, event, arg):
if (
event == "exception"
and arg[0] is AssertionError
and frame.f_code.co_name == "conn_handler"
):
assertions.append(arg[1])
return trace

def process_request(ws, request):
return ws.respond(http.HTTPStatus.FORBIDDEN, "Forbidden")

def handler(ws):
self.fail("handler must not run")

with run_server(handler, process_request=process_request) as server:
with self.assertRaises(InvalidStatus) as raised:
with connect(get_uri(server)):
self.fail("did not raise")
self.assertEqual(
str(raised.exception),
"server rejected WebSocket connection: HTTP 403",
)
threading.settrace(trace)
try:
with run_server(handler, process_request=process_request) as server:
with self.assertRaises(InvalidStatus) as raised:
with connect(get_uri(server)):
self.fail("did not raise")
self.assertEqual(
str(raised.exception),
"server rejected WebSocket connection: HTTP 403",
)
finally:
threading.settrace(None)

self.assertEqual(assertions, [])

def test_process_request_raises_exception(self):
"""Server returns an error if process_request raises an exception."""
Expand Down