3proxy/tests/cases/httpsrv_ops.py
Vladimir Dubrovin 629a978c00
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Has been cancelled
help: the features of the build listed, and the tests skip what they need
3proxy --help (and the usage message of a bad invocation) now lists
what the build was made with: TLS and its backend, RADIUS, PCRE, IPv6,
UNIX sockets, the built-in HTTP server, transparency, ODBC and the
optional proxy services. The test runner reads the list before the
first case and the cases state the features they need with
t.skip_unless(), so a build without a feature skips its cases instead
of failing them; a binary too old to report anything skips the cases
with needs and runs the rest.
2026-10-30 14:24:46 +03:00

81 lines
3.2 KiB
Python

"""The built-in HTTP server: the echo and data operations."""
import time
def run(t):
if not t.skip_unless("httpsrv"):
return
srv = t.free_port()
t.start("httpsrv_ops", f"""
log
auth iponly
allow *
http echo * /echo**
http data * /data
http data * /small 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")