Changes for version 0.17 - 2026-08-17

  • Fixed t/14-futures.t failing on every perl whose Future is older than the one it was developed against - reported by CPAN Testers against 0.16 on 5.20.0, 5.22.2 and 5.24.0 with "Expected __ANON__(Future.pm line 1140) to return a Future".
  • A route may now be declared as one hashref, with the handler under `cb`:
    • post "/upload" => { cb => "Web::File#create", max_body => 50_000_000 };
    • instead of the positional form, which is unchanged and stays the one `punk new` generates:
      • post "/upload" => "Web::File#create", { max_body => 50_000_000 };
  • New route option { compress => 0 }, which opts a route out of the server response compression Hyperman 0.25 adds. Punk does not compress - that belongs to the write path - so the option is spelled as a plain response header, Content-Encoding: identity, which the server honours and strips.
  • New `max_body` keyword and per-route { max_body => N }: refuse a request whose CONTENT_LENGTH is over a ceiling, with the same 413 an oversize API operation gets.
  • Punk::Upload documents what an upload actually costs: it arrives whole in memory before a handler sees it, ->save is a write and not a stream, and `max_body` does not reduce the memory.
  • SECURITY: the `markdown` mount reflected the request path into the Location header of its canonical 301 (the redirect that strips a trailing slash or a .md suffix). PATH_INFO reaches a PSGI app percent-DECODED, so that echoed bytes the client chose: a decoded CR/LF split the response at any mount point, and at a root mount "//evil.example/" came back as a protocol-relative 301 off the site. Found while fixing the same class of bug in Punk::OAuth2 (CVE-2026-75628). The redirect now only names a path that IS a page - the stripped target is looked up in the page table first - so the only thing it can echo is one of the mount's own keys. Anything else falls through to the 404 it was always going to get. pmd_redirect also stops at the first control byte, in case a mount prefix ever carries one.

Documentation

the Punk command line

Modules

a MVC web framework
the per-application registry and boot compiler
the authentication battery
password hashing
cross-origin resource sharing
single-use CSRF tokens
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
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
serving files from a directory
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 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

Provides

in bench/apps/cat-lib/BenchCat.pm
in bench/apps/cat-lib/BenchCat/Controller/Root.pm