3proxy/tests/cases/httpsrv_ops.py
Vladimir Dubrovin 73fbf9d262 Add tests
2026-08-25 18:03:50 +03:00

79 lines
3.1 KiB
Python

"""The built-in HTTP server: the echo and data operations."""
import time
def run(t):
srv = t.free_port()
t.start("httpsrv_ops", f"""
log
auth iponly
allow *
http * /echo* echo
http * /data data
http * /small data size=64
httpsrv -p{srv}
""", ports=[srv])
url = f"http://127.0.0.1:{srv}"
# --- echo: request introspection ---------------------------------
r = t.http(url + "/echo?a=1")
t.eq(200, r.status, "echo answers 200")
t.contains(r, "method=GET", "echo reports the method")
t.contains(r, "path=/echo", "echo reports the path")
t.contains(r, "query=a=1", "echo reports the query")
t.contains(r, "peer.addr=127.0.0.1", "echo reports the peer address")
t.contains(r, f"host=127.0.0.1:{srv}", "echo reports the Host header")
# the glob is the wildcard-matched tail, which is how admin routes its
# sub-pages
r = t.http(url + "/echoXYZ")
t.contains(r, "glob=XYZ", "echo reports the glob text")
t.contains(r, "glob.len=3", "echo reports the glob length")
# --- data: generated payload -------------------------------------
t.eq(1000, t.http(url + "/data?size=1000").length, "data honours size")
t.eq(0, t.http(url + "/data?size=0").length, "data size=0 sends an empty body")
t.eq(64, t.http(url + "/small").length, "data takes its size from the rule")
t.eq(1000, t.http(url + "/small?size=1000").length,
"the query overrides the rule parameters")
# a size past one block exercises the send loop
t.eq(70000, t.http(url + "/data?size=70000").length,
"data spans several blocks")
t.eq(70000, t.http(url + "/data?size=70000&block=1024").length,
"data honours the block size")
# --- status and framing ------------------------------------------
t.eq(404, t.http(url + "/data?size=10&status=404").status,
"data honours the status")
t.eq(503, t.http(url + "/data?size=10&status=503").status,
"data returns 503 when asked")
t.eq(200, t.http(url + "/data?size=10&status=99").status,
"an out-of-range status falls back to 200")
r = t.http(url + "/data?size=100")
t.eq("100", r.header("Content-Length"), "an identity reply sets Content-Length")
r = t.http(url + "/data?size=100&chunked=1")
t.eq("chunked", r.header("Transfer-Encoding"),
"a chunked reply sets Transfer-Encoding")
t.eq(None, r.header("Content-Length"),
"a chunked reply omits Content-Length")
t.eq(100, r.length, "a chunked body decodes to the size asked for")
t.eq(70000, t.http(url + "/data?size=70000&chunked=1").length,
"a chunked body spans several blocks")
# --- delay --------------------------------------------------------
start = time.time()
t.http(url + "/data?size=4096&block=1024&delay=100")
elapsed = time.time() - start
if elapsed >= 0.3:
t.ok("delay slows the transfer")
else:
t.fail("delay slows the transfer", ">=0.3s", f"{elapsed:.2f}s")
# --- unmatched ----------------------------------------------------
t.eq(404, t.http(url + "/nosuchthing").status, "an unmatched URL gives 404")