Rich Bowen [Fri, 5 Jun 2026 19:55:22 +0000 (19:55 +0000)]
Update misc/relevant_standards to reflect current RFCs
Replace obsolete RFC references (2616, 2396, 4346, 2617) with their
modern successors. Add sections for TLS, proxying, WebSocket, CGI, and
WebDAV. Remove HTML section (httpd does not validate content markup).
Remove stale "not yet complete" notice and dead skrb.org errata link.
Jim Jagielski [Fri, 5 Jun 2026 19:07:15 +0000 (19:07 +0000)]
Perl test asserts the opposite of what the server does, and only "passes"
because LWP fabricates the header client-side. Clean this mess up. LWP
is weird.
Jim Jagielski [Fri, 5 Jun 2026 17:48:53 +0000 (17:48 +0000)]
test: port recent httpd-tests 2.4.68 changes to pytest_suite
Reflect the following t/ changes into test/pytest_suite:
* expr: file()/filesize() are restricted in 2.4.68+; gate the
expected results (None => parse error 500) and move file()
into the 2.3.13 block.
* mod_headers: support an optional expected-status field; add
malformed-regex -> 500 and 2.4.68 file()-in-htaccess -> 500.
* mod_dav: PUT to a .DAV state subdir is blocked (403) in
2.4.68+, else 201.
* mod_proxy_html: add multi-substitution buffer-realloc tests
(literal and regex) with ProxyHTMLBufSize 256.
Joe Orton [Fri, 5 Jun 2026 16:54:38 +0000 (16:54 +0000)]
* modules/proxy/mod_proxy_beacon.c (beacon_resolve, beacon_parse_url,
beacon_verify): Use ap_strstr_c and ap_strchr_c for const-correct
string searches, fixing -Werror=discarded-qualifiers errors.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@193504013f79535-47bb-0310-9956-ffa450edef68
Joe Orton [Thu, 4 Jun 2026 15:48:00 +0000 (15:48 +0000)]
* modules/proxy/mod_proxy_ftp.c (proxy_ftp_dir_filter): Use
ap_os_escape_path() with ap_escape_html() instead of
ap_escape_uri() for href attributes in generated directory
listing links.
Rich Bowen [Thu, 4 Jun 2026 15:22:55 +0000 (15:22 +0000)]
docs: Rewrite AllowOverride Options= warning
The existing note about implicit disabling of Options was difficult
to parse. Rewrite as a type="warning" note with:
- Clear statement that the restriction controls enabling, not disabling
- Explanation of absolute vs relative (+/-) Options syntax
- Concrete example showing how inherited options get implicitly disabled
Joe Orton [Thu, 4 Jun 2026 09:03:50 +0000 (09:03 +0000)]
mod_proxy_html: Simplify to use the ap_varbuf API.
* modules/filters/mod_proxy_html.c: Include util_varbuf.h.
(saxctxt): Replace buf/offset/avail members with struct ap_varbuf vb.
(DEFAULT_BUFSZ): New macro.
(normalise): Take struct ap_varbuf * parameter instead of char *.
(preserve, pappend): Remove functions, replaced by ap_varbuf_grow
and ap_varbuf_strmemcat respectively.
(dump_content): Use ap_varbuf for regex substitutions via
ap_varbuf_regsub, avoiding manual buffer resizing with
preserve/memmove/memcpy. Use a temporary ap_varbuf for building
regex replacement results.
(pcharacters, pcomment): Use ap_varbuf_strmemcat and ap_varbuf_strcat
in place of pappend.
(pendElement): Check vb.strlen instead of offset.
(pstartElement): Use ap_varbuf for attribute URL rewriting with the
same ap_varbuf_regsub approach. Use a temporary ap_varbuf for
regex replacements.
(proxy_html_filter): Initialize the ap_varbuf with a clamped bufsz.
(proxy_html_merge): Use DEFAULT_BUFSZ macro.
Assisted-by: Claude Opus 4.6 (claude-opus-4-6)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@193497513f79535-47bb-0310-9956-ffa450edef68
Jim Jagielski [Wed, 3 Jun 2026 23:23:47 +0000 (23:23 +0000)]
pytest_suite: port Perl todo/xfail gaps found when testing against 2.4.x
Three test files had behaviour differences between the Python port and
the original Perl framework tests when run against a 2.4.x build
(tested with Apache/2.4.68-dev at /opt/local2/apache2).
test_pr64339.py -- LWP vs httpx default charset for raw bodies
For /doc.notxml the proxy returns Content-Type: application/notreallyxml
with no charset and a Latin-1 body. LWP defaults to ISO-8859-1 for
charset-less responses; httpx defaults to UTF-8, decoding 0xF3 as a
replacement character and failing the body match. Add _lwp_text() to
mirror LWP: use the Content-Type charset when present, else Latin-1.
test_session.py -- port Perl @todo for PR 58171 and PR 56052
session.t marks subtests 53/54 (Session writable after decode failure,
PR 58171) and 88/89 (Session writable after expired, PR 56052) as
unconditional @todo. The Python port dropped this bookkeeping. On
2.4.x, ap_session_load() sets zz=NULL on a decode failure and allocates
a fresh session the memoising provider never sees, so nothing is saved;
trunk uses memset-in-place to preserve the provider pointer. Add a
_check(..., todo=True) helper that downgrades failures to warnings,
matching Perl's todo semantics for both subtests.
test_proxy_html.py -- xfail two metafix cases that fail on 2.4.x
other header with Content-Type present: mod_proxy_html metafix emits
no http-equiv headers for meta_contenttype.html because the leading
charset Content-Type meta is consumed by the xml2enc path on 2.4.x.
empty content value: metafix locates the content value via a
case-insensitive search for 'content'; the header name X-Empty-Content
itself matches first, so no value is extracted. Gate both via
pytest.xfail when the server is < 2.5.0, leaving assertions active on
trunk.
Jim Jagielski [Wed, 3 Jun 2026 22:32:17 +0000 (22:32 +0000)]
test/pyhttpd: move pyproject.toml and uv.lock under pyhttpd/
The pyproject.toml and uv.lock belong to the pyhttpd test suite, so move
them from test/ into test/pyhttpd/ where the package itself lives.
Update runtests-pyhttpd.sh to use 'uv sync --project pyhttpd/' and
reference the venv at pyhttpd/.venv/. Fix pyhttpd/env.py to look for
the venv at the same level (pyhttpd/.venv/) instead of the parent dir.
Jim Jagielski [Wed, 3 Jun 2026 21:25:44 +0000 (21:25 +0000)]
test/pytest_suite: fix more tests broken by httpx auto-decompression
httpx transparently inflates gzip/deflate response bodies (it keeps the
Content-Encoding header but .content/.text are the decoded plaintext). Three
more tests asserted on the body of a compressed response and so were wrong:
- pr43939 / pr17629: re-POSTed r.content (decoded plaintext, not the gzip
stream) through the inflate input filter -- same round-trip bug as
pr49328/deflate.
- reflector: 'assert r.text != payload' could never hold, since httpx
decoded the gzip body straight back to the payload.
Generalise the GET_RAW helper into a raw_response(method, path, ...) that
streams the response, reads iter_raw() (undecoded bytes), and stashes them on
.raw_content while leaving .status_code/.headers intact -- so tests can assert
on both the raw body and the headers. GET_RAW now delegates to it; update the
three tests to use raw_response/.raw_content.
The length-based tests (rwrite, passbrigade, getfile, byterange7) are
unaffected: they measure len(.content) after decoding, which equals the
original length regardless of transfer compression.
Jim Jagielski [Wed, 3 Jun 2026 21:14:57 +0000 (21:14 +0000)]
test/pytest_suite: fix deflate round-trip tests to use raw gzip bytes
httpx auto-decompresses gzip responses, so .content returned the decoded
plaintext rather than the gzip stream. Re-POSTing that plaintext with
Content-Encoding: gzip made mod_deflate's inflate input filter fail,
breaking the round-trip assertions in test_pr49328 and test_deflate.
Add a GET_RAW client helper that streams the response and reads iter_raw(),
returning the body undecoded (the analog of LWP not auto-decoding), and use
it in both tests so they exercise a genuine gzip -> inflate round-trip.
Jim Jagielski [Wed, 3 Jun 2026 20:27:40 +0000 (20:27 +0000)]
pyhttpd: fix built-in module loading, add venv support
* detect statically compiled modules via `httpd -l` and skip
LoadModule for them, fixing startup failure when log_config_module
(or others) are built into the httpd binary
* add pyproject.toml with all required Python dependencies
(cryptography, python-multipart, websockets, pyopenssl, etc.)
* add runtests-pyhttpd.sh that creates/reuses a .venv via uv or
plain python3+pip, mirroring pytest_suite/runtests.sh
* prepend .venv/bin to PATH when launching httpd so CGI scripts
forked by httpd also use the venv's Python and find all packages
* update run-all-tests.sh to delegate pyhttpd runs to the new script
Jim Jagielski [Wed, 3 Jun 2026 19:05:31 +0000 (19:05 +0000)]
test/pytest_suite: auto-create .venv via python3+pip when uv is unavailable
runtests.sh already bootstrapped the virtualenv with `uv sync` when uv
was present, but exited with an error when it was not. Fall back to
`python3 -m venv .venv && .venv/bin/pip install -e .` so the suite is
self-bootstrapping on systems that have only a stock Python 3 install.
Bring the pytest suite to parity with the canonical source:
* Add 25 previously-missing test fixture files (deflate images, expires
placeholders, data PNG, rewrite dbm, ssl .pfa placeholders, .empty
dir-keepers, headers htaccess) that several module tests require; their
absence caused spurious 404 failures.
* Set svn:executable on the CGI/shell/perl scripts (and the negotiation
and xbithack content files that carry the bit upstream) so CGI tests no
longer fail with 500 on a fresh checkout.
* Stop tracking the .htaccess/htpasswd files that the tests rewrite at run
time (setenvif/htaccess/.htaccess, autoindex2/dir_broken/.htaccess,
autoindex2/dir_protected/htpasswd) and add svn:ignore for them, matching
the original Perl Apache::Test framework which never versioned them.
* Add per-directory svn:ignore for c-module build artifacts, generated
t/conf configs, generated CGI scripts and runtime dirs, plus a recursive
svn:global-ignores for Python caches (__pycache__, *.pyc, .venv, etc.).
Jim Jagielski [Wed, 3 Jun 2026 17:28:47 +0000 (17:28 +0000)]
pytest_suite: add missing modules/access/htaccess/ directory and index.html
test_access.py (mod_access_compat Order/Allow/Deny tests) writes
.htaccess at runtime for each permutation and then GETs index.html to
verify access is granted or denied. The directory and its empty
index.html must pre-exist; .htaccess itself is written by the test.
Jim Jagielski [Wed, 3 Jun 2026 17:24:44 +0000 (17:24 +0000)]
pytest_suite: fix hardcoded absolute paths in .htaccess files
Both files were committed with /Users/jjagielski/... paths that only
work on one developer's machine.
autoindex2/dir_protected/.htaccess: AuthUserFile now uses a path
relative to ServerRoot (Apache 2.4+ resolves these against the
configured ServerRoot, which the test framework sets to pytest_suite/t/).
setenvif/htaccess/.htaccess: file() argument in SetEnvIfExpr now uses
%{DOCUMENT_ROOT} instead of a hardcoded absolute path.
Jim Jagielski [Wed, 3 Jun 2026 17:21:22 +0000 (17:21 +0000)]
pytest_suite: fix startup failures and add missing Perl helper templates
Three bugs fixed in the pytest framework:
1. cmodules.py: compiled C test modules were not rebuilt when apxs changed
(e.g. upgrading from Apache 2.4 to 2.5). The staleness check now also
compares the .so mtime against apxs itself, so a newer apxs always
triggers a rebuild and prevents API-signature mismatches (AP24 vs AP25).
Add clean_modules() to remove all apxs build artifacts (make clean
equivalent), exposed as --clean-modules pytest option and routed only
to pytest_suite (not pyhttpd) in run-all-tests.sh.
2. server.py: httpd was started without -DFOREGROUND, so the MPM parent
forked and exited (code 0) before the port opened. The framework
misread the fork-exit as a crash and killed the running daemon.
Add -DFOREGROUND so the Popen process IS the httpd parent.
3. Missing Perl helper scripts: t/conf/extra.conf.in declares a prg-type
RewriteMap (numbers-prg) whose program file did not exist, causing
httpd to refuse to start. More broadly, all *.pl CGI scripts,
ext_filter programs, rewrite-map programs, and the SSL passphrase
helper referenced by the config and tests were absent.
Add the full set of *.pl.PL source templates (copied from the
httpd-tests framework), covering:
- t/conf/ssl/httpd-passphrase.pl.PL
- t/htdocs/apache/http_strict/send_hdr.pl.PL (new dir)
- t/htdocs/modules/cgi/ (28 CGI scripts)
- t/htdocs/modules/ext_filter/ (2 filter programs, new dir)
- t/htdocs/modules/negotiation/query/test.pl.PL
- t/htdocs/modules/rewrite/ (numbers, numbers2, db)
generate_pl_scripts() regenerates the .pl executables from these
templates at each test-session start with the correct local perl shebang.
Joe Orton [Wed, 3 Jun 2026 10:40:17 +0000 (10:40 +0000)]
CI: Update used actions to use newer Node.js than 20
CI: Update upload-artifact action, drop unnecessary Ubuntu 22.04 fix
CI: Drop 'shell: cmd', use PowerShell for the Windows workflow
CI: Print used CMake version for Windows workflow
Submitted by: Vladimír Chlup <vchlup ibm.com>
Github: closes #660
Jim Jagielski [Tue, 2 Jun 2026 15:50:29 +0000 (15:50 +0000)]
test/h2: ignore AH02430 for the whole TestRfc9113 class
test_h2_203_02 intentionally triggers AH02430 (illegal response header
char). Over HTTP/2 the error is logged late during stream teardown and
can produce several lines, so the per-case ignore_recent() raced them
and they leaked into a later test's check_error_log(). Move the ignore
to an autouse class fixture (as conftest.py does for AH10400/AH00045)
and add HttpdErrorLog.remove_ignored_lognos() to restore on teardown.
Rich Bowen [Tue, 2 Jun 2026 12:56:14 +0000 (12:56 +0000)]
Fix RedirectMatch regex in ACME exemption recipe (bug 70084)
The negative lookahead (?!...) is zero-width and non-capturing, so
the original pattern matched only the leading slash and \$1 was
undefined. Add a capturing group (.*)$ after the lookahead so that
\$1 contains the remainder of the URL-path.
Performance:
- Accept drain loop: motorz_io_accept now drains the kernel accept queue
in one poll wakeup (do/while until EAGAIN, admission-disabled, or die_now)
instead of one connection per round-trip through apr_pollset_poll. Eliminates
O(N) poll wakeups for N burst connections.
- Hot-path log levels: 25 APLOG_DEBUG calls on the per-request path demoted to
APLOG_TRACE6/TRACE7/TRACE8, matching event MPM practice. Error and admission-
control events remain at DEBUG.
- Redundant pollset_remove removed: the defensive apr_pollset_remove in
motorz_io_process is gone from the common dispatch path (connection is already
claimed before reaching here); isolated to the clogging-filter branch where it
is actually needed.
- Admission control: added active-thread saturation check (active >= threads_per_child)
alongside the existing idle==0 and pending>=hi checks, catching slow-client /
keep-alive-heavy saturation where the task queue appears empty but all workers
are blocked in I/O. apr_size_t underflow fix: read total before idle, clamp
active = (total > idle) ? total - idle : 0, preventing spurious disable during
graceful restart.
- Hysteresis low-water mark tightened from 50% to 75% of ThreadsPerChild, so
the listener re-enables sooner after a burst subsides.
Bug fixes:
- Clogging-filter timer race (use-after-free): the SSL/clogging path in
motorz_io_process bypassed motorz_conn_claim(). A pending timer could fire
concurrently while the worker was inside ap_run_process_connection(), dispatching
a timeout worker on the same scon. Fixed by replacing the bare pollset_remove
with motorz_conn_claim(), which atomically disarms both the pollset entry and
the timer under poller->mtx.
- motorz_resume_suspended: restore c->sbh before ap_run_resume_connection().
motorz_suspend_connection() NULLs c->sbh (matching event's notify_suspend);
without this fix any module calling ap_update_child_status(c->sbh) after
resume dereferenced NULL.
- SERVER_BUSY_READ scoreboard update: add ap_update_child_status(scon->sbh,
SERVER_BUSY_READ, NULL) before ap_run_process_connection(), matching event MPM
and fixing misleading mod_status output where motorz connections showed as
SERVER_READY throughout the read/process phase.
- requests_this_child data race: written by the accepting poller thread, read
by the supervisor main thread. Declared volatile to prevent stale cached reads
across threads.
- conn_id always zero: every connection was created with conn_id=0, breaking
%{connection} log formats and any module keying state on c->id. Now derived
as ID_FROM_CHILD_THREAD(my_child_num, atomic_seq), matching worker/event MPM
formula for globally unique IDs across children and connections.
- ap_create_sb_handle hardcoded child 0: all connections reported as child 0
in the scoreboard, making mod_status show all activity in slot [0][0].
Now passes my_child_num so each child's activity appears in the correct slot.
- Worker threads not drained on exit: apr_thread_pool_destroy() is now called
in clean_child_exit() before apr_pool_destroy(pchild), joining all workers
and preventing use-after-free in ap_log_error / apr_pool_clear after the
pool is torn down.
- ThreadsPerChild 1 throughput collapse: the hysteresis low-water mark becomes
(1*3)/4=0, so listeners only re-enable when the task queue is completely
empty. Added startup/runtime warnings (APLOGNO 10555/10556) advising
ThreadsPerChild >= 4. next-number advanced to 10557.
Multi-poller scale-out (PollersPerChild):
- motorz_core_t no longer holds a single pollset/timeout_ring/mtx/recycle-list;
these are moved to per-poller motorz_poller_t contexts.
- Each poller owns its pollset, skiplist timer ring, ring mutex, and lock-free
MPSC transaction-pool recycle list, so pollers never contend with each other.
- Connections are sharded round-robin to pollers at accept time (scon->poller);
pool recycling returns to the accepting poller's free-list (scon->pool_poller).
- PollersPerChild directive added (0 = auto from online CPUs, capped at 8).
- Listener admission control and the pipe-of-death/generation supervision are
isolated to poller 0 and the main-thread supervisor respectively.
- AP_MPMQ_CAN_SUSPEND / motorz_resume_suspended hook wired in for full
async-suspend support (fix for CONN_STATE_SUSPENDED lifecycle).
- Non-blocking lingering close: replaced blocking ap_lingering_close() with
motorz_start_lingering_close() / motorz_lingering_close() that hand the
draining socket back to the poll loop with a bounded linger timeout.
- Pool cleanup (motorz_conn_pool_cleanup) cancels the timer under poller->mtx
so pool destruction never leaves a dangling skiplist entry.
Async HTTP/2 handoff -- ENABLED (MOTORZ_ENABLE_ASYNC 1):
- motorz reports AP_MPMQ_IS_ASYNC=1 / AP_MPMQ_CAN_WAITIO=1. motorz_io_process()
implements CONN_STATE_ASYNC_WAITIO: arm the pollset for read/write per
c->cs->sense under Timeout and re-dispatch into PROCESSING, mirroring event.
New APLOGNOs 10557-10559.
- Clogging-filter branch honors the hook-returned connection state
(WRITE_COMPLETION / ASYNC_WAITIO / SUSPENDED) and maps KEEPALIVE to
WRITE_COMPLETION instead of force-closing to LINGER. h2 c2 connections set
clogging_input_filters unconditionally, so the old behavior collapsed h2
keep-alive into one-shot connections.
- Forward-declare motorz_update_listeners() (called from motorz_io_accept
before its definition; an implicit declaration is a hard error under strict
C). Replaced a dead duplicate clean_child_exit prototype.
The async-handoff churn bug -- FIXED in mod_http2 (h2_session.c):
Under async handoff mod_http2 hands the master (c1) connection back to the MPM
between requests; motorz re-dispatches it on a fresh worker. Under rapid HTTP/2
connection churn this raced mod_http2's stream lifecycle: a client's graceful
GOAWAY drove the c1 session straight to DONE -> CONN_STATE_LINGER, and the MPM
close ran m_stream_cleanup()/h2_c2_abort() on any stream whose secondary
connection (c2) had emitted its response but not yet called c2_prod_done() --
silently dropping that response (~0.2-3% under h2load -n.. -c50 -m1).
The fix establishes the invariant "a c1 connection is closed only after every
stream's c2 has finished and flushed", in two points in h2_session.c:
* h2_session_ev_remote_goaway(): a graceful GOAWAY (error code 0) with
streams still in flight no longer transits to H2_SESSION_ST_DONE. It RSTs
only the unprocessed streams and keeps the session running so the in-flight
streams complete and their c2 output is written. (An error GOAWAY, or one
with no open streams, still goes to DONE immediately.) This also matches
RFC 9113: a peer GOAWAY stops new streams, it does not abort streams at or
below its last-stream-id.
* H2_SESSION_ST_IDLE handling: once those streams drain (open_streams == 0)
and the remote has shut down, send our GOAWAY and go to DONE from IDLE.
Reaching DONE only here -- after the c2s are done and flushed -- keeps the
close from racing an in-flight c2.
This benefits mpm_event too and is a conformance improvement, not just a
motorz workaround. MOTORZ_ENABLE_ASYNC remains a single flip point (set 0 to
fall back to advertising IS_ASYNC=0) should a regression ever reappear.
Hardening of the fix (this change):
- motorz.c, smoke.sh: corrected stale "async DISABLED" comments that still
described the old workaround while the code already enabled async.
- h2_session.c: documented the liveness bound -- keeping the session alive on a
graceful GOAWAY cannot pin c1 open indefinitely, since a wedged c2 is bounded
by its own request Timeout, which drops open_streams and lets c1 reach IDLE.
- h2_session.h: documented the open_streams threading invariant the fix now
relies on (c1-thread only; async re-dispatch is successive not concurrent, so
no atomics/volatile needed; decrements to 0 only after each c2 has flushed).
Tests (server/mpm/motorz/test/): setup.sh configures+builds httpd; run-all.sh
runs the smoke, HTTP/1.1, and HTTP/2-over-TLS suites; bench.sh compares motorz
vs event throughput. The async assertions expect async ON
(CONN_STATE_ASYNC_WAITIO arms / "returning to mpm c1 monitoring" appears).
The churn regression measures the fix correctly (two pitfalls, documented in
MOTORZ.README and encoded in the tests):
* Assert on RESPONSE LOSS (started - succeeded), NOT on h2load's "failed"
total. "failed" also counts connection-establishment errors (ephemeral
port / accept-queue pressure on busy loopback) which are environmental and
appear with and without the fix; only started > succeeded is this bug.
* Measure at LogLevel info, NOT trace8. The bug is a Heisenbug; trace8 slows
the hot path enough to hide it, so a churn assertion run under trace8
passes even with the fix removed (vacuous). The load-bearing churn
regression is in run-http2.sh at info; smoke.sh runs at trace8 for its
state-machine traces, so its churn check is a gross-sanity pass only.
Full analysis, reproduction recipe, and the fix are in
server/mpm/motorz/MOTORZ.README ("HTTP/2 async handoff").
Official mod_http2 pytest suite (test/modules/http2/): test_h2_106_02 now
skips on MPMs that do not register ServerLimit (i.e. mpm_motorz, whose static
fixed-size process pool makes StartServers the hard daemon limit, so ServerLimit
is meaningless and unregistered). The test's ServerLimit/MaxConnectionsPerChild
config is a syntax error there; prefork/worker/event still run it unchanged.
MaxConnectionsPerChild itself IS supported by motorz (a core directive honored by
the supervisor). Validated: full http2 suite green on both event and motorz
(only known flaky proxy-backend tests aside), and the motorz custom suite
(smoke/http1/http2) passes with 0 churn response-loss.
Docs and packaging: add the mpm_motorz manual page (docs/manual/mod/motorz.xml
+ .meta, registered in allmodules.xml) documenting the threading model, async
handling, admission control, and the PollersPerChild directive; add a CHANGES
entry; and insert motorz into the default-MPM fallback chain (server/mpm/
config2.m4) between event and worker.
Rich Bowen [Sat, 30 May 2026 22:29:02 +0000 (22:29 +0000)]
Switch HTML output from XHTML 1.0 Strict to HTML5
Change output method to "html" and emit <!DOCTYPE html> instead of
the XHTML 1.0 Strict doctype. Remove XHTML namespace declarations
and xml:lang attributes from all XSL stylesheets. Remove explicit
Content-Type meta tag (now auto-generated by the HTML serializer).
This resolves validate-xhtml failures caused by HTML5 features
(aria-* attributes, inline SVG) that are invalid under the
XHTML 1.0 Strict DTD.
Stefan Eissing [Fri, 29 May 2026 09:09:41 +0000 (09:09 +0000)]
*) mod_http2: update to version 2.0.42
Fix excessive file description use for non-TLS frontend connections when
sending files. Fixes <https://github.com/icing/mod_h2/issues/325>
Rich Bowen [Tue, 26 May 2026 10:11:21 +0000 (10:11 +0000)]
docs: Modernize install.xml
- Remove mirrors reference and binary releases (both retired)
- Update all external links to https
- Update version examples to current 2.4.66/2.4.67
- Replace two-step gzip/tar with single tar xzf
- Reword download section for source builds
- Consolidate verification link to verification.html
- Remove minimizing language (easy, simple, simply)
- Add language="sh" to all highlight blocks
- Update disk space: 200 MB build (was 50), 50 MB installed (was 10)
- Replace deprecated ntpdate/xntpd with systemd-timesyncd/chrony
- Remove outdated Perl 5.003 version floor
- Update release examples from dead 2.0/2.2 to 2.4/2.6
- Update 'Mac OS X, Solaris' to 'macOS'
- Requirements intro: 'building' → 'building and running'
Stefan Eissing [Tue, 26 May 2026 07:42:30 +0000 (07:42 +0000)]
*) mod_http2: update to version 2.0.40
Fix error handling on upload requests when server runs out of file
handles that left beam bucket callbacks in place, potentially using
no longer valid references. Only applies on platforms with pipes
and file descriptor limits not healthy for a network server.
Rich Bowen [Mon, 25 May 2026 20:20:58 +0000 (20:20 +0000)]
docs: Add SVG source for RewriteCond syntax diagram, regenerate PNG
Recreate syntax_rewritecond as editable SVG with color-coded callouts
for TestString, CondPattern, and [Flags]. Matches style of RewriteRule
syntax diagram.