Changes for version 0.002005 - 2026-06-30
- Features
- sse.http.response.* decline events (PAGI spec). Before sse.start, an application may decline the stream and return a normal HTTP response (404/401/403/204/redirect/...) by sending sse.http.response.start + sse.http.response.body instead of sse.start. This finally makes an unmatched SSE route return a real HTTP 404 rather than crashing the connection, and gives EventSource the spec's 204 stop-reconnect path. Implemented for both HTTP/1.1 and HTTP/2, reusing the normal HTTP response machinery. First-send-wins: after sse.start a decline raises, and after sse.http.response.start a stream event raises. EventValidator accepts the decline events (status required integer; headers arrayref; more integer).
- sse.close send-event (PAGI spec). Applications can now end an SSE stream explicitly -- immediately and decoupled from returning -- instead of only by returning. Implemented for both HTTP/1.1 (chunked terminator) and HTTP/2 (final END_STREAM frame). An optional `reason` is server-side metadata only and is never written to the wire. After sse.close a repeat sse.close is a no-op and any other send raises; a transport-gone close (client disconnect) stays a silent no-op. Returning after the final sse.send remains valid and terminates identically. EventValidator accepts sse.close.
Documentation
PAGI application server
HTTP/1.1, HTTP/2, WebSocket, and Security Compliance Documentation
Modules
PAGI Reference Server Implementation
Non-blocking file I/O for PAGI::Server internals
Per-connection state machine
Connection state tracking for HTTP requests
Dev-mode event field validation
HTTP/1.1 protocol handler
HTTP/2 protocol handler using nghttp2
PAGI application loader and server runner
Outbound flow-control introspection for a connection
Provides
in lib/PAGI/Server/Protocol/HTTP2.pm
Examples
- examples/01-hello-http/README.md
- examples/01-hello-http/app.pl
- examples/02-streaming-response/README.md
- examples/02-streaming-response/app.pl
- examples/03-request-body/README.md
- examples/03-request-body/app.pl
- examples/04-websocket-echo/README.md
- examples/04-websocket-echo/app.pl
- examples/05-sse-broadcaster/README.md
- examples/05-sse-broadcaster/app.pl
- examples/06-lifespan-state/README.md
- examples/06-lifespan-state/app.pl
- examples/07-extension-fullflush/README.md
- examples/07-extension-fullflush/app.pl
- examples/08-tls-introspection/README.md
- examples/08-tls-introspection/app.pl
- examples/11-job-runner/README.md
- examples/11-job-runner/app.pl
- examples/11-job-runner/lib/JobRunner/HTTP.pm
- examples/11-job-runner/lib/JobRunner/Jobs.pm
- examples/11-job-runner/lib/JobRunner/Queue.pm
- examples/11-job-runner/lib/JobRunner/SSE.pm
- examples/11-job-runner/lib/JobRunner/WebSocket.pm
- examples/11-job-runner/lib/JobRunner/Worker.pm
- examples/11-job-runner/public/css/style.css
- examples/11-job-runner/public/index.html
- examples/11-job-runner/public/js/app.js
- examples/12-utf8/README.md
- examples/12-utf8/app.pl
- examples/README.md
- examples/backpressure-test/README.md
- examples/backpressure-test/app.pl
- examples/worker-pool-prototype.pl