Skip to content
Merged
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
7 changes: 7 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@ def client_ca(certipy):
# self.internal_ssl_cert,
# cafile=self.internal_ssl_ca,
)
# FIXME: generate certs with Authority Key defined for strict checking
# upstream PR: https://github.com/LLNL/certipy/pull/23/
# avoids Missing Authority Key Identifier SSL errors
# with new defaults in Python 3.13
ssl_context.verify_flags &= ~ssl.VERIFY_X509_STRICT
AsyncHTTPClient.configure(None, defaults={"ssl_options": ssl_context})
return record['files']['ca']

Expand Down Expand Up @@ -311,6 +316,8 @@ def _check_ssl(proxy, client_ca):
)
context.check_hostname = True
context.verify_mode = ssl.VerifyMode.CERT_REQUIRED
# required for Python 3.13 until we get a certipy update
context.verify_flags &= ~ssl.VERIFY_X509_STRICT
context.load_cert_chain(proxy.ssl_cert, proxy.ssl_key)

url = urlparse(Config.public_url)
Expand Down
39 changes: 33 additions & 6 deletions tests/dummy_http_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,59 @@
from http import HTTPStatus

import websockets
from packaging.version import parse as V

_old_ws = V(websockets.__version__) < V("14")


# websockets 14 changed APIs
# drop _old_ws logic when we drop Python 3.8
# _old_ws signature: (path, request_headers, port)
async def process_request(connection, request, port):
if _old_ws:
path = connection
request_headers = request
else:
path = request.path
request_headers = request.headers

async def process_request(path, request_headers, port):
if path.endswith("/ws"):
return None

headers = {
"Content-Type": "text/plain",
"Host": request_headers.get("Host", "None"),
"Origin": request_headers.get("Origin", "None"),
}
return (HTTPStatus.OK, headers, str(port).encode("utf8"))

if _old_ws:
return (HTTPStatus.OK, headers, str(port).encode())
else:
response = connection.respond(HTTPStatus.OK, str(port))
response.headers.update(headers)
return response


async def send_port(websocket):
_ip, port = websocket.local_address
await websocket.send(str(port))

async def send_port(websocket, path):
await websocket.send(str(websocket.port))

async def main(port, *, _start_future=None, _stop_future=None):
# allow signaling a stop (in tests)
if _stop_future is None:
_stop_future = asyncio.Future()

async def main(port):
async with websockets.serve(
send_port,
host="127.0.0.1",
port=port,
process_request=partial(process_request, port=port),
):
if _start_future:
_start_future.set_result(None)
# wait forever
await asyncio.Future()
await _stop_future


if __name__ == "__main__":
Expand Down
40 changes: 40 additions & 0 deletions tests/test_dummy_http_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import asyncio

import websockets
from tornado.httpclient import AsyncHTTPClient

from .dummy_http_server import main


# quick test that the dummy http server for tests works!
async def test_dummy_server(request):
port = 5678
start_future = asyncio.Future()
stop_future = asyncio.Future()
# stat dummy server, wait for it to start
main_future = asyncio.ensure_future(
main(port, _start_future=start_future, _stop_future=stop_future)
)
await asyncio.wait(
[start_future, main_future], timeout=5, return_when=asyncio.FIRST_COMPLETED
)
if main_future.done():
main_future.result()

try:
http_url = f"http://127.0.0.1:{port}/test"
ws_url = f"ws://127.0.0.1:{port}/ws"
resp = await AsyncHTTPClient().fetch(http_url)
assert resp.body == str(port).encode()

ws_url = f"ws://127.0.0.1:{port}/ws"

async with websockets.connect(ws_url) as websocket:
ws_port = await websocket.recv()
assert ws_port == str(port)
finally:
stop_future.cancel()
try:
await main_future
except asyncio.CancelledError:
pass