functional2/http_server: add some example misbehaviour routes
Part of https://git.lix.systems/lix-project/lix/issues/949. This also fixes a bug where our SO_REUSEADDR wasn't done before bind was called and thus didn't work as intended. Co-authored-by: Commentator2.0 <lix@crystal-cavern.systems> Change-Id: Ie69fd594a32d7a6f538fb66d9d2cac6fe117d563
This commit is contained in:
committed by
Commentator2.0
parent
556012e409
commit
faa0b4f291
@@ -11,7 +11,7 @@ import socket
|
||||
import threading
|
||||
from queue import Queue
|
||||
import aiohttp.web as web
|
||||
|
||||
import aiohttp.http_writer as http_writer
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -42,12 +42,12 @@ class EventTS(asyncio.Event):
|
||||
self.target_loop.call_soon_threadsafe(super().set)
|
||||
|
||||
|
||||
def _make_localhost_socket() -> tuple[socket.socket, int]:
|
||||
"""Creates a localhost-bound socket with an auto-assigned port."""
|
||||
def _make_localhost_socket(port: int = 0) -> tuple[socket.socket, int]:
|
||||
"""Creates a localhost-bound socket with an auto-assigned port (unless specified)."""
|
||||
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||
sock.bind(("::1", 0))
|
||||
# Shouldn't matter because we dynamically allocate ports, but this is generally preferred.
|
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
sock.bind(("::1", port))
|
||||
_, port = sock.getsockname()[:2]
|
||||
|
||||
return (sock, port)
|
||||
@@ -73,10 +73,10 @@ def _server_thread(app: web.Application, sock: socket.socket, shutdown_ev_q: Que
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def http_server(app: web.Application):
|
||||
def http_server(app: web.Application, port: int = 0):
|
||||
"""
|
||||
Creates an http server on an automatically chosen port on the host
|
||||
running the given web.Application, gives you the port for it.
|
||||
Creates an http server on an automatically chosen port (if not given) on
|
||||
the host running the given web.Application, gives you the port for it.
|
||||
|
||||
The server is run on a separate thread.
|
||||
"""
|
||||
@@ -89,7 +89,7 @@ def http_server(app: web.Application):
|
||||
sock = None
|
||||
shutdown_ev = None
|
||||
try:
|
||||
sock, port = _make_localhost_socket()
|
||||
sock, port = _make_localhost_socket(port=port)
|
||||
thr = threading.Thread(
|
||||
target=_server_thread,
|
||||
args=(app, sock, shutdown_ev_q),
|
||||
@@ -109,18 +109,40 @@ def http_server(app: web.Application):
|
||||
|
||||
def dev_main():
|
||||
"""A little test server for poking at this manually"""
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
async def root(_req: web.Request) -> web.Response:
|
||||
# sadly required to make this function async
|
||||
await asyncio.sleep(0.01)
|
||||
return web.Response(body="hello world")
|
||||
|
||||
app = web.Application()
|
||||
app.add_routes([web.get("/", root)])
|
||||
async def eof(req: web.Request) -> web.StreamResponse:
|
||||
# sadly required to make this function async
|
||||
await asyncio.sleep(0.01)
|
||||
writer: http_writer.StreamWriter = req.writer # type: ignore
|
||||
assert writer.transport
|
||||
writer.transport.close()
|
||||
return web.StreamResponse()
|
||||
|
||||
with http_server(app) as httpd:
|
||||
async def eof_after_headers(req: web.Request) -> web.StreamResponse:
|
||||
resp = web.StreamResponse()
|
||||
resp.headers["content-length"] = "1337"
|
||||
await resp.prepare(req)
|
||||
await resp.write_eof()
|
||||
writer: http_writer.StreamWriter = req.writer # type: ignore
|
||||
assert writer.transport
|
||||
writer.transport.close()
|
||||
return resp
|
||||
|
||||
app = web.Application()
|
||||
app.add_routes(
|
||||
[web.get("/", root), web.get("/eof", eof), web.get("/eof_after_headers", eof_after_headers)]
|
||||
)
|
||||
|
||||
with http_server(app, 1337) as httpd:
|
||||
logger.info("Listening on http://[::1]:%d", httpd.port)
|
||||
time.sleep(3600)
|
||||
while True:
|
||||
time.sleep(3600)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user