Changes for version 0.46 - 2026-09-08

  • ADDS: $c->req->xml - the request body parsed as XML through File::Raw::XML's C ABI, as a File::Raw::XML::Document. The parse is strict and takes no options: a DOCTYPE is refused wherever it stands, so external entities, XXE and the billion laughs are not reachable from a request. Parsed once per request.
  • ADDS: $c->xml($doc, $status?) - a Document, a Node or a string of markup as an application/xml response.
  • FIXES: a File::Raw::XML::Document returned from a handler, or set as a Punk::Response body, was JSON-encoded - it is a blessed reference like any other. It is now written as markup, which is also what makes respond_to(xml => sub { $doc }) answer application/xml.
  • Punk::Test takes `xml => $doc_or_string` as a request body and answers ->xml with the parsed response.
  • NOTE: $c->validate's `auto` source recognises only application/json, so a schema on an XML POST validates the query string rather than the body. Name the source to be sure of it.
  • File::Raw::XML 0.03 is a new prerequisite.
  • FIXES: the file cache's single-flight lock judged its holder's age from whole-second st_mtime, so an age could read a second too high and a `lock_wait` under a second was spent before it began
  • FIXES: a single-flight lock that could not be attempted at all - a path that would not form - answered "you won", so every caller computed and the herd ran unprotected with nothing said. It is counted now and reported as `lock_errors` from the file store's stats.
  • t/0733-auth-sqitch.t asserted Sqitch's own deploy output, which is translated - under LC_ALL=de_DE a successful deploy reports "+ users ........ OK" and the test failed.

Documentation

the Punk command line

Modules

a MVC web framework
the per-application registry and boot compiler
async and await in Punk apps, controllers and models
the authentication battery
password hashing
cross-origin resource sharing
single-use CSRF tokens
a pluggable cache with TTL
a cache store on disk, shared by the whole worker pool
an in process cache store, bounded by bytes
the punk command line: registry, dispatcher and commands
YAML configuration with secrets kept out of the file
the per-request object
base class for Punk controllers
the development error page
an async result that runs on the loop, or blocks
scaffold a new Punk application
security response headers
a level-based logger
the storage-agnostic model tier
the default DBI backend for Punk models
a non-blocking backend for Punk models
a directory of markdown as a documentation site
the api mount: spec-first operations
base class for Punk plugins
content addressed storage for uploads
Content-Security-Policy with a per request nonce
ETags, Last-Modified and 304s for dynamic responses
liveness and readiness probes that mean different things
translations and language negotiation
Idempotency on unsafe methods
a Prometheus endpoint whose labels cannot run away
give every request an id
sitemap.xml and robots.txt from the route table
rate limiting and IP blocking over Hyperman's shared arena
a lazy wrapper over the PSGI environment
a response builder
the compiled-at-boot route tables (XS)
the handle an under returns
a Server-Sent Events stream
the bounded body of a ranged send_file response
signed cookie sessions
server-side sessions, on any store
serving files from a directory
a streamed response for an ordinary route
an in-process test client for Punk applications
a pure-Perl RFC 6455 codec for testing WebSocket servers
the client side of one WebSocket connection
the transaction a < $c-txn >> block receives
the outbound HTTP agent on the context
an uploaded file from a multipart form
collecting request validation
the Template::Stencil view engine
the pluggable view engine registry (XS)
a WebSocket connection
pub/sub groups of WebSocket connections