PAGI

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

    on Unix socket connections
  - Validate --socket-mode is a 4-digit octal value (reject ambiguous input)
  - Harden --listen parser: paths starting with / or . always treated as Unix
    sockets (prevents mis-parsing paths containing colons)
  - Runner load_server omits host/port when socket or listen is provided

  [Test Fixes]
  - Use condition-based waiting in HTTP/2 SSE keepalive test (eliminates flakiness)
  - Gate timing-sensitive multiworker/heartbeat tests behind RELEASE_TESTING

0.001020 - 2026-03-16
  [Security Hardening]
  - Reject requests with both Transfer-Encoding and Content-Length (RFC 9112)
  - Validate Transfer-Encoding per RFC 9112 Section 6.1 (chunked must be final)
  - Validate trailer headers for CRLF injection
  - Validate SSE event/id/retry fields against newline injection
  - Prevent code injection via loop_type parameter (block eval, not string eval)
  - Fix TLS config to allow TLS 1.3 negotiation (SSL_version trailing colon)

  [Session Middleware Refactor]
  - Pluggable State/Store architecture for PAGI::Middleware::Session
  - State classes: Cookie (default), Header, Bearer, Callback
  - Store classes: Memory (default, dev/test), with async Future-based interface
  - PAGI::Session standalone helper with strict get() (dies on missing key)
  - PAGI::Session accepts raw data, scope hashref, or object with ->scope
  - Bulk operations: set(k1 => v1, k2 => v2), delete(@keys), slice(@keys), clear()
  - Session destroy lifecycle: deletes from store, clears cookie via State::clear()
  - Session regenerate lifecycle: generates new ID, deletes old, preserves data
  - Idempotency: middleware skips if pagi.session already in scope
  - Reserved keys (_destroyed, _regenerated) documented as middleware-consumed flags
  - Store::Cookie extracted to separate CPAN dist (PAGI-Middleware-Session-Store-Cookie)

  [Bug Fixes]
  - disable_tls skips TLS setup instead of dying
  - Recompile access log formatter on configure() changes
  - Weaken $self in _pause_accepting timer closure (reference cycle fix)
  - Replace Future::IO->load_impl('IOAsync') with use Future::IO::Impl::IOAsync
    (fixes compatibility with Future::IO 0.22+)

  [Cleanup]
  - Remove unused _log_connection_stats method

0.001019 - 2026-02-19
  [New Features]
  - Router: rewrite _compile_path() as tokenizer with proper regex escaping,
    so literal path segments containing regex metacharacters (e.g., /foo.bar)
    are matched literally instead of as patterns
  - Router: inline constraint syntax {name:pattern} for path parameters
    (e.g., /user/{id:\d+}) validated during dispatch
  - Router: chainable constraints() method for applying regex constraints
    to named path parameters after route definition
  - Router: any() multi-method matcher supporting wildcard ('*') and
    explicit method lists (e.g., any [qw(GET POST)] => '/path' => $handler)
  - Router: named routes and uri_for() now support {name:pattern} syntax
    and any() routes
  - Router: group() for organizing routes under a common prefix, with three
    forms: callback (sub), router-object, and string (auto-require). Supports
    middleware, nesting, named route namespacing via as(), and conflict detection
  - Router: mount() now accepts a string class name with auto-require and
    to_app dispatch
  - SSE over HTTP/2 with streaming DATA frames, keepalive comments, and
    disconnect handling
  - Add PAGI::Utils::Random module for cryptographically secure random bytes
  - Rate limiter: periodic cleanup and safety valve for expired buckets
  - CORS middleware: warn when configured with wildcard origins and credentials

  [Security Fixes]
  - Fix XSS in Debug middleware panel by escaping scope values in HTML output
  - Add max_chunk_size limit (default 1MB) to HTTP/1.1 chunked transfer
    parser to prevent denial-of-service via unbounded chunk sizes
  - Use cryptographically secure random bytes (via /dev/urandom with
    Crypt::URandom fallback) in RequestId, CSRF, and Session middleware
    instead of rand()
  - Default session cookie SameSite=Lax to prevent CSRF via cross-site requests
  - Fix double URL-decoding in Static middleware that could allow path traversal

  [Bug Fixes]
  - Fix HTTP/2 path decoding to match HTTP/1.1 decoding pipeline
  - Fix HTTP/2 WebSocket path decoding to match HTTP/1.1 pipeline
  - Require Net::HTTP2::nghttp2 0.007+ for HTTP/2 support (was unversioned)

  [Improvements]
  - Extract _format_sse_event() and _format_sse_comment() helpers and
    protocol-abstracted keepalive writer for consistent SSE formatting
    across HTTP/1.1 and HTTP/2

0.001018 - 2026-02-15
  [Bug Fixes]
  - Skip HTTP/2 subtests when Net::HTTP2::nghttp2 is not installed, fixing
    CPAN tester failures on systems without optional nghttp2 dependency

0.001017 - 2026-02-11
  [New Features]
  - HTTP/2 support (experimental). Requires Net::HTTP2::nghttp2. Enable with
    --http2 flag. Supports ALPN negotiation (h2/http1.1 over TLS), cleartext
    h2c via connection preface detection, WebSocket over HTTP/2 (RFC 8441),
    streaming responses with backpressure, and configurable protocol settings
    (h2_max_concurrent_streams, h2_initial_window_size, etc.)
  - Worker heartbeat monitoring for multi-worker mode. Parent process detects
    workers with blocked event loops via Unix pipe heartbeat and replaces them
    with SIGKILL + respawn. Default 50s timeout (heartbeat_timeout option,
    --heartbeat-timeout CLI flag). Only detects event loop starvation — async
    handlers using await are unaffected regardless of duration.
  - Custom access log format strings (--access-log-format). Supports atoms
    like %a (address), %s (status), %D (duration μs), %b (body size).
    Enables structured JSON logging via format string.
  - Track response body size in access log (%b atom)

  [Bug Fixes]
  - Fix TLS performance cliff at 8+ concurrent connections caused by
    per-connection SSL context creation parsing the entire CA bundle.
    Shared SSL context via SSL_reuse_ctx gives ~26x throughput improvement.
  - Fix TLS in multi-worker mode — workers now SSL-upgrade connections
    in on_stream rather than relying on listener-level TLS
  - Fix SSE wire format to handle CRLF, LF, and bare CR line endings
    per the SSE specification
  - Fix multi-worker shutdown escalation — SIGKILL timer now fires
    correctly when workers don't exit after SIGTERM
  - Fix multi-worker parameter pass-through for server options
  - Fix flaky multi-worker TLS test

  [Improvements]
  - Add on_ssl_error callback to TLS listener setup for cleaner error
    handling (suppresses "EV: error in callback" noise)
  - Cache Server header string to avoid per-response interpolation
  - Merge double header loop in serialize_response_start
  - Cache access log timestamp at per-second granularity
  - Cache client_host in access log to avoid per-request getpeername syscall
  - Skip HTTP/2 tests when Net::HTTP2::nghttp2 is not installed
  - Skip SSE tests when Future::IO is not installed
  - Remove unused Sys::Sendfile recommendation from cpanfile

0.001016 - 2026-01-31
  [New Features]
  - Add query parameter parsing to PAGI::SSE: query_params(), query_param(),
    raw_query_params(), raw_query_param() methods mirroring PAGI::Request
    and PAGI::WebSocket APIs
  - pagi-server now auto-configures Future::IO for IO::Async if installed,
    enabling seamless use of Future::IO-based libraries (Async::Redis, etc.)
    and PAGI::SSE->every(). Reports configuration in non-production mode.

  [Breaking Changes]
  - PAGI::Server (the module) no longer auto-configures Future::IO.
    pagi-server (the CLI) handles this automatically. Programmatic users
    of PAGI::Server must configure Future::IO themselves if using
    Future::IO-based libraries. See PAGI::Server "LOOP INTEROPERABILITY".

  [Improvements]
  - PAGI::SSE->every() now provides a clear error message if Future::IO
    backend is not configured, with example code showing how to fix it
  - New PAGI::Server documentation section "LOOP INTEROPERABILITY" explains
    Future::IO configuration for programmatic usage

0.001015 - 2026-01-18
  [New Features]
  - Add query parameter parsing to PAGI::WebSocket: query_params(), query_param(),
    raw_query_params(), raw_query_param() methods mirroring PAGI::Request API



( run in 0.842 second using v1.01-cache-2.11-cpan-140bd7fdf52 )