NAME
Punk::WebSocket - a WebSocket connection
SYNOPSIS
# in the app
websocket '/chat' => 'WS::Chat#join';
# MyApp::Controller::WS::Chat
sub join {
my ($c, $ws) = @_; # after a validated upgrade
$ws->on(open => sub {
my ($ws) = @_;
Punk::WebSocket::Room->named('lobby')->join($ws);
});
$ws->on(message => sub {
my ($ws, $text) = @_;
Punk::WebSocket::Room->named('lobby')->broadcast($text);
});
$ws->on(close => sub {
my ($ws, $code, $reason) = @_;
Punk::WebSocket::Room->named('lobby')->leave($ws);
});
}
DESCRIPTION
One WebSocket connection. The handler for a websocket route is called with the Punk::Context and this object once the upgrade handshake has been validated and answered; it wires the events it cares about and returns. Reading, framing, ping/pong and the closing handshake then run on the worker's event loop with no further Perl involvement until a message completes.
Frames are decoded in C to RFC 6455, strictly: unmasked client frames, fragmented or over-long control frames and reserved opcodes are protocol errors (close 1002), text payloads and close reasons must be valid UTF-8 (1007), and a message over max_message_size is refused from the frame header before it is buffered (1009).
EVENTS
$ws->on($event => sub { ... }), one handler per event; an unknown event name croaks. Every handler receives the connection first.
open
($ws)- the handshake is complete.message
($ws, $text)- a complete text message, character-decoded.binary
($ws, $bytes)- a complete binary message.ping
($ws, $payload)/ pong($ws, $payload)- a pong is sent automatically before the ping event fires.close
($ws, $code, $reason)- fires exactly once, for a clean close or a dropped connection (code 1006).error
($ws, $message)- a handler died, or the codec rejected the peer's framing.
A handler that dies does not take the worker down: the error event fires and the connection is closed with 1011.
METHODS
send($text)
send_binary($bytes)
Queue a message. Writes are buffered and drained on the loop, so a slow consumer never blocks the worker (past write_buffer_limit the connection is closed with 1008).
ping($payload?)
pong($payload?)
close($code = 1000, $reason = '')
Start the closing handshake; the close event fires when it completes or times out.
state / is_open / is_closing / is_closed
protocol
The negotiated subprotocol, or undef.
fd
The underlying file descriptor.
SEE ALSO
Punk, Punk::WebSocket::Room, "detach" in Hyperman.
AUTHOR
LNATION <email@lnation.org>
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION <email@lnation.org>.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)