Revision history for WebDyne
3.028 - 2026-09-08
* Add optional startup and shutdown coderefs to WebDyne::PAGI. Callbacks
receive the application object and lifespan scope; returned Futures are
awaited before acknowledgement. Exceptions and failed Futures produce
the corresponding lifespan failure event. Missing callbacks preserve
existing behaviour; shutdown callbacks run only when the server delivers
shutdown.
* Clear shared PAGI diagnostics before synchronous HTTP, SSE and WebSocket
page setup, after request body buffering. Recovered errors no longer
leak into later requests, while errors from the current request remain
available to its error handler.
* Add regression coverage for synchronous and asynchronous lifespan
callbacks, callback and transport failures, and diagnostic isolation
across sequential requests and interleaved HTTP/SSE body reads.
3.027 - 2026-09-07
* Use lazy load ("require") for modules only required at certain decision paths
3.026 2026-09-05
* Required Carp 1.50 or newer so Devel::Confess preserves the original
PAGI send failure on older Perls instead of reporting a stack-argument
copy error. Installed Future::IO explicitly in CI to run the PAGI
multipart tests instead of skipping them.
* Retained the PAGI response Future before awaiting it to avoid a Perl
5.38 segmentation fault when Devel::Confess builds a stack trace for a
failed response send. Exception tracing remains enabled.
* Added regression coverage for failed PAGI response body sends,
checking that the original error propagates without sending
additional events.
3.025 2026-09-05
* Preserved repeated Set-Cookie headers in PAGI responses and flattened
repeated PSGI response headers into separate scalar pairs. Apache
header snapshots now retain repeated values; their documented snapshot
semantics remain unchanged.
* Bound PAGI and PSGI HTTP request bodies with WEBDYNE_CGI_POST_MAX (512
KiB by default) before page dispatch. Added support for bodies without
Content-Length and robust PSGI short-read handling, with oversized
bodies rejected using HTTP 413 and invalid or incomplete PSGI bodies
using HTTP 400.
* Corrected PAGI mounted-path handling relative to root_path and
normalized outgoing HTTP header names to lowercase.
* Buffered bounded URL-encoded PAGI SSE form bodies before page setup,
awaited SSE close sends, and returned explicit denial responses for
SSE setup failures and WebSocket handshakes without valid page
callbacks. Multipart SSE submissions remain unsupported.
* Accepted URL-encoded form Content-Type parameters such as charset.
Apache body readers now support missing Content-Length, reject
incomplete reads, and enforce defensive size checks for buffered and
streaming input. Multipart forms without a length are buffered for
CGI::Simple parsing.
* Documented Apache LimitRequestBody as the primary request-size
protection. Adapter checks also enforce WEBDYNE_CGI_POST_MAX; uncaught
defensive exceptions currently produce HTTP 500.
* Added regression coverage for the request-adapter fixes to MANIFEST
and made the new PSGI tests skip when optional Plack dependencies are
unavailable. Refreshed the WebDyne 3.0 release overview and upgrade
guidance.
* Added GitHub build-provenance attestations for release distribution
archives, alongside existing Cosign signatures. README.md now explains
verification with gh attestation verify against aspeer/WebDyne,
including archives downloaded from CPAN mirrors. Prefixed
release-script shell globs with ./ to prevent filenames being
interpreted as options.
* Removed the Plack dependency from static-file subrequests used by
standalone utilities. The historical PSGI::Static helper now inherits
from Request::Fake; cpanfile no longer requires Plack::Request. Added
regression coverage for utilities without Plack/PAGI, binary and empty
static files, missing files, and PSGI/PAGI parent requests.
* Reviewed and expanded the DocBook guide against the current code.
Corrected examples and runtime defaults, and added guidance on PAGI
async state and await boundaries, SSE and WebSocket completion,
request and response handling, uploads, escaping, body limits, and
production deployment.
3.024 2026-09-05
* Fixed PAGI multipart form uploads by staging bounded request bodies
before synchronous CGI::Simple parsing. Binary uploads and form fields
now work with asynchronous request delivery, and multipart bodies
above WEBDYNE_CGI_POST_MAX return HTTP 413.
* Fixed source, template, and compiled-cache handling for files with an
mtime of zero, as found on WebAssembly and other virtual filesystems.
Distinguished undefined cache timestamps from valid epoch-dated caches
when deciding whether to compile or load a page.
* Added the missing Fcntl import in WebDyne::Util for file-open flags.
* Added regression coverage for repeated asynchronous multipart uploads,
upload size limits, and zero-timestamp source, template, and cache
files. Optional PAGI tests now check dependencies before loading async
modules, and the session-cookie test skips the SameSite assertion when
the installed CGI::Simple cannot serialize that attribute.
3.023 2026-08-25
* Moved PSGI and PAGI wrapper initialization fully into
WebDyne::PSGI and WebDyne::PAGI. The webdyne.psgi and webdyne.pagi
scripts now use the shared application builder, so configured
middleware and document-root .webdyne.conf.pl loading behave the same
for wrapper scripts and directly constructed applications.
* Disabled PSGI and PAGI static-file middleware by default. Enable it
explicitly with static => 1, --static in the helper scripts, or the
WEBDYNE_PSGI_STATIC or WEBDYNE_PAGI_STATIC configuration constant.
This avoids serving static assets unexpectedly from directly
constructed applications.
* Added regression coverage for wrapper static-option forwarding and
ensured static middleware does not expose files with disallowed
extensions.
3.022 2026-08-25
* Hardened the helper script defaults for the built-in WebDyne indexer.
webdyne.psgi, webdyne.pagi, and webdyne.apache now leave index handling
disabled by default unless DOCUMENT_DEFAULT, a user option file, or an
explicit --index option enables it.
* Added WEBDYNE_INDEX_SOURCE_ENABLE and --view-source support for the
helper scripts. The built-in index page source viewer is now disabled
unless both index handling and source viewing are explicitly enabled,
preserving the directory listing/debugging workflow without exposing
page source by default.
* Added PSGI and PAGI application builder support for wrapper-style
initialization, including optional static handling and document-root
.webdyne.conf.pl loading via the new constructor options. The helper
scripts now opt in to this behaviour while direct
WebDyne::PSGI->new(...)->to_app and WebDyne::PAGI->new(...)->to_app
construction retains conservative defaults.
* Fixed PSGI API fallback path traversal by rejecting dot path segments
before route discovery and verifying discovered API files remain inside
the document root using canonical relative-path checks. Added
regression coverage for traversal attempts and normal API routing.
* Restored end-of-string matching for WebDyne PSP filenames so files
such as report.psp.pdf are not treated as executable PSP pages.
This fixes a double-extension execution regression introduced when
WEBDYNE_PSP_EXT became configurable.
* Re-enabled CGI form value escaping by default and fixed the
WebDyne::HTML::Tiny entity encoder override so
WEBDYNE_CGI_AUTOESCAPE works as documented. Sticky text, password, and
file form fields now escape request-derived values before rendering
them into HTML attributes.
* Applied automatic HTML escaping to request, environment, and method
substitution operators (+{...}, *{...}, and ^{...}) when
WEBDYNE_CGI_AUTOESCAPE is enabled. The raw ${...} substitution operator
remains available for trusted, already-rendered values.
* Added secure session cookie defaults and configuration constants for
Secure, HttpOnly, and SameSite attributes. WebDyne sessions now emit
Secure, HttpOnly, and SameSite=Lax cookies by default, with documented
constants for deployments that need to adjust those attributes.
* Preserved <start_html> shortcut version overrides and added regression
coverage for local-configuration isolation so tests are not affected by
a developer's document-root .webdyne.conf.pl.
* Updated the XML documentation, markdown sidecars, MANIFEST, and test
suite for the new helper defaults, index source controls, escaping
behaviour, PSP extension matching, PSGI/PAGI initialization, API
traversal checks, and session cookie flags.
3.021 2026-08-24
* Extended wdlint to inspect inline Perl chunks, processing instructions,
and substitution expressions in addition to __PERL__ sections. Each
chunk is checked independently so later syntax errors are still reported
after an earlier chunk fails. Added line-preserving regression coverage.
* Added require and import attributes to <start_html>, using the same
dependency-loading and function-import behaviour as <perl>. Declared
dependencies are loaded before normal, SSE, and WebSocket handlers are
dispatched.
* Passed CGI parameter hashes to PAGI SSE and WebSocket subroutines as
their second argument, allowing async handlers to use request
parameters explicitly across await points.
* Fixed URL-encoded form POST handling under PAGI by asynchronously
buffering request bodies before synchronous CGI::Simple parsing. Kept
the cached body available to the WebDyne PAGI request adapter and
avoided crossing localized environment scopes during await. Added
repeated-request regression coverage for the former Future panic.
* Added documentation and WebDyne authoring guidance for start_html
dependencies, PAGI parameters, SSE/WebSocket handlers, HTMX fragments,
and the required hx-vals="js:{ ... }" syntax when supplying values from
PSP pages.
* Added release-board and pizza-order SSE/HTMX demonstration pages,
including WebDyne-rendered fragments, status refreshes, and PAGI
handler examples. Kept these developer demos and scratch material out
of distribution manifests.
3.020 2026-08-20
* Changed <api> route pattern semantics so patterns are relative to the
discovered API PSP file path. For example, api.psp owning
/api/user/42 now uses pattern="/user/:id" rather than
pattern="/api/user/:id". This is a breaking change for existing
<api> pages.
* Updated PSGI and PAGI API fallback dispatch to strip the full API PSP
mount path from PATH_INFO before passing requests to Router::Simple,
keeping API route declarations independent of document-root location.
* Updated API examples, release examples, tests, and local authoring
guidance to use the new suffix-only <api pattern> convention.
* Documented the WebDyne 3.020 <api> pattern breaking change in the XML
documentation and tag reference.
3.013 2026-08-16
* Normalized generated no_* wrapper options to numeric booleans so
--dump_opt output is stable across Perl and Data::Dumper versions.
* Made the webdyne.apache wrapper tests less sensitive to whitespace in
Apache::TestRunPerl argument dumps and avoided macOS APXS probing by
using a fake test apxs helper.
* Improved PAGI smoke-test diagnostics by allowing PAGI::Test::Client
application exceptions to surface in t/14-pagi.t instead of comparing
only against a generic Internal Server Error response.
* Added PAGI::Tools to the webdyne.pagi wrapper test prerequisite gate,
matching the wrapper's runtime check and avoiding noisy failures on
partial PAGI installations.
3.012 2026-08-10
* Disabled the redundant webdyne.apache ulimit probe, avoiding noisy
stderr on restricted CPAN smoke hosts where raising the core-file
ulimit is not permitted.
* Guarded developer-only doc/example scans in the generated Makefile so
CPAN install and smoke-test runs remain quiet when the documentation
source tree is not shipped in the distribution tarball.
3.011 2026-08-07
* Extended wdrender --quiet/--silent to suppress advisory warnings about
missing optional HTML::Tidy5 or syntax-highlighting modules while
leaving rendering behaviour unchanged.
* Updated wdrender regression coverage so --header output remains clean
on machines without libtidy-devel and HTML::Tidy5 installed.
* Made wdrender head-insert tests tolerant of harmless HTML/CSS
whitespace differences while still checking that the default head
insert is present or absent as requested.
3.010 2026-08-07
* Fixed duplicate response header emission when WebDyne handlers set
headers through the request object, avoiding malformed HTTP response
headers in PSGI and other runtimes.
* Fixed wdrender --header output so response headers are included
consistently regardless of colour, line-number, pretty-print, or tidy
settings.
* Added wdrender regression coverage for duplicate Content-Type headers
and for --header behaviour with colour/tidy output enabled and
disabled.
* Added explicit filename override support for WebDyne::PSGI and
WebDyne::PAGI helper applications, allowing tools such as wdrender to
render a fixed source file while still exercising PSGI or PAGI request
handling.
* Documented that the WebDyne::PSGI and WebDyne::PAGI filename option
is an application-level source-file override and always wins over
normal request-path filename derivation.
* Propagated wdrender --no-head-insert/--head-insert handling through
PSGI, PAGI, and temporary Apache/mod_perl render paths.
* Simplified wdrender test-file routing for PSGI and PAGI helper modes
by passing an explicit filename override instead of depending on
request path rewriting.
3.009 2026-08-06
* Added style_prepend/style_append and script_prepend/script_append
pseudo attributes for <start_html>, allowing pages to add resources
around configured WEBDYNE_START_HTML_PARAM defaults without replacing
them.
* Clarified <start_html> default-attribute override behaviour: page
attributes replace matching WEBDYNE_START_HTML_PARAM values, while the
new prepend/append variants preserve and extend configured style/script
resources.
* Documented <start_html> resource ordering for linked styles versus
include_style content, and external scripts versus include_script
content.
* Made PSGI and PAGI wrapper configuration loading consistent by loading
DOCUMENT_ROOT/.webdyne.conf.pl when the app is built, including when
webdyne.psgi or webdyne.pagi is loaded by an external server.
* Clarified root .webdyne.conf.pl loading versus per-request directory
.webdyne.conf.pl handling, where only WEBDYNE_DIR_CONFIG is read from
PSP-directory config files.
* Added regression coverage for <start_html> style/script extension
attributes and PSGI/PAGI external-loader root configuration loading.
3.008 2026-08-04
* Added REST-style <api> route discovery and PATH_INFO mapping to
WebDyne::PAGI, bringing PAGI API support in line with PSGI.
* Added per-application API filename caches for PSGI and PAGI. API
filename or route-structure changes may require a server restart.
* Ensured PAGI emits a valid empty HTTP response when an API document
produces no body, avoiding PAGI lint errors.
* Clarified that Apache mod_perl does not provide automatic extensionless
API route discovery without additional Apache rewrite or routing rules.
* Added integration coverage for PSGI and PAGI API routing, caching,
normal PSP requests, and 404 handling.
* Fixed labelled <textfield> rendering so label-wrapped text inputs
retain the correct HTML input type.
* Added default/defaults handling for grouped form controls and popup
menus, aligning generated form state with the documented attributes.
* Added labelled textfield render fixtures and included them in the
distribution manifest.
* Updated the XML and generated Markdown documentation for the latest
API, form-control, and demo example behaviour.
3.005 2026-08-02
Major Version 3 release.
* Added PAGI runtime support through WebDyne::PAGI and the
webdyne.pagi wrapper, including HTTP, server-sent event, WebSocket,
and lifespan request handling.
* Added a common request abstraction for standalone, Apache/mod_perl,
PSGI, and PAGI execution environments.
* Refactored PSGI support into WebDyne::PSGI and expanded runtime
handling for document roots, default documents, directory indexes,
static files, and API routes.
* Added webdyne.apache for temporary local Apache/mod_perl execution
without requiring a permanent system Apache configuration.
* Expanded wdapacheinit to support broader Apache installations,
APXS discovery, installation and uninstall workflows, dry-run
operation, and platform-specific configuration layouts.
* Expanded wdrender to exercise multiple request backends, including
fake, PSGI, PAGI, and mod_perl, with support for request methods,
headers, parameters, response inspection, and comparison testing.
* Added test-file modes to command-line compilation and rendering
utilities.
* Added a bundled default stylesheet for generated WebDyne pages and
improved the appearance of default directory index output.
* Added Docker runtime selection between PSGI and PAGI, with
environment-variable tuning for server workers, timeouts, backlog,
connection limits, and request body sizes.
* Improved request and static-file safety, including path traversal,
upload, multipart, error handling, and binary response coverage.
* Reworked the documentation into a DocBook/MkDocs build with
generated utility and module reference pages.
* Added extensive examples and expanded automated test coverage for
runtime backends, wrappers, static handling, APIs, SSE, WebSockets,
and command-line utilities.
* Removed the old WebDyne::CGI::PSGI adapter in favour of the new
request and runtime abstraction.
2.021 2025-11-07
* Added multi-line <start_html> attributes for scripts, styles, and
related inclusions.
* Prevented WebDyne substitution inside executable JavaScript blocks.
* Added default viewport metadata and expanded head inclusion support,
including array-valued includes.
* Added Alpine/Vue attribute compatibility handling.
2.018 2025-10-29
* Added the <htmx> tag for request-aware HTML fragment rendering.
* Made directory indexes and static files available by default through
the PSGI wrapper.
* Improved HTML tree handling, constant importing, and error reporting.
2.017 2025-10-27
* Added the <api> tag for lightweight JSON API responses using
Router::Simple path matching.
2.015 2025-10-22
* Added the wdlint utility for checking Perl syntax in __PERL__
sections of PSP files.
* Added the default PSGI directory index page and --index support.
2.014 2025-10-18
* Replaced the CGI.pm-based HTML generation path with CGI::Simple and
WebDyne::HTML::Tiny.
* Refactored compilation and evaluation handling around the new HTML
generation backend.
* Added the JSON tag, alternate div-based WebDyne syntax,
application/perl script blocks, and expanded HTML5 tag handling.
* Added PSGI/Plack support to the main WebDyne distribution, including
command-line document-root and default-document selection.
* Added exported WebDyne::html() and WebDyne::html_sr() functions for
standalone PSP rendering.
* Added WebDyne::Template to the core distribution and added PSGI
static-file serving through --static.
* Added WEBDYNE_HEAD_INSERT for injecting common content into generated
document heads.
* Added Docker build files and container-oriented development support,
including automatic dependency installation from a mounted cpanfile.