File Coverage

blib/lib/PAGI/Context/WebSocket.pm
Criterion Covered Total %
statement 41 41 100.0
branch n/a
condition 2 3 66.6
subroutine 34 34 100.0
pod 30 32 93.7
total 107 110 97.2


line stmt bran cond sub pod time code
1             package PAGI::Context::WebSocket;
2              
3 18     18   95 use strict;
  18         26  
  18         657  
4 18     18   61 use warnings;
  18         22  
  18         13205  
5              
6             our @ISA = ('PAGI::Context');
7              
8             # ── Underlying PAGI::WebSocket accessor ──────────────────────────────
9              
10             sub websocket {
11 78     78 0 826 my ($self) = @_;
12 78   66     301 return $self->{_websocket} //= do {
13 40         4170 require PAGI::WebSocket;
14 40         253 PAGI::WebSocket->new($self->{scope}, $self->{receive}, $self->{send});
15             };
16             }
17              
18 62     62 0 323 sub ws { shift->websocket }
19              
20             # ── Connection lifecycle ─────────────────────────────────────────────
21              
22 23     23 1 279 sub accept { shift->ws->accept(@_) }
23 4     4 1 95 sub close { shift->ws->close(@_) }
24              
25             # ── Send methods ─────────────────────────────────────────────────────
26              
27 1     1 1 26 sub send_text { shift->ws->send_text(@_) }
28 1     1 1 25 sub send_bytes { shift->ws->send_bytes(@_) }
29 1     1 1 27 sub send_json { shift->ws->send_json(@_) }
30              
31 1     1 1 27 sub try_send_text { shift->ws->try_send_text(@_) }
32 1     1 1 27 sub try_send_bytes { shift->ws->try_send_bytes(@_) }
33 1     1 1 27 sub try_send_json { shift->ws->try_send_json(@_) }
34              
35 1     1 1 29 sub send_text_if_connected { shift->ws->send_text_if_connected(@_) }
36 1     1 1 26 sub send_bytes_if_connected { shift->ws->send_bytes_if_connected(@_) }
37 1     1 1 49 sub send_json_if_connected { shift->ws->send_json_if_connected(@_) }
38              
39             # ── Receive methods ──────────────────────────────────────────────────
40              
41 1     1 1 27 sub receive_text { shift->ws->receive_text(@_) }
42 1     1 1 93 sub receive_bytes { shift->ws->receive_bytes(@_) }
43 1     1 1 49 sub receive_json { shift->ws->receive_json(@_) }
44              
45             # ── Iteration helpers ────────────────────────────────────────────────
46              
47 1     1 1 51 sub each_message { shift->ws->each_message(@_) }
48 1     1 1 52 sub each_text { shift->ws->each_text(@_) }
49 1     1 1 47 sub each_bytes { shift->ws->each_bytes(@_) }
50 1     1 1 28 sub each_json { shift->ws->each_json(@_) }
51              
52             # ── State inspection ─────────────────────────────────────────────────
53             # is_connected overrides the base Context method (which checks TCP-level
54             # pagi.connection) to use WebSocket handshake state instead — that is
55             # what handler code actually cares about.
56              
57 3     3 1 101 sub is_connected { shift->ws->is_connected }
58 2     2 1 83 sub is_closed { shift->ws->is_closed }
59 1     1 1 610 sub close_code { shift->ws->close_code }
60 1     1 1 3 sub close_reason { shift->ws->close_reason }
61              
62             # ── Protocol metadata ────────────────────────────────────────────────
63              
64 1     1 1 12 sub subprotocols { shift->ws->subprotocols }
65 1     1 1 13 sub http_version { shift->ws->http_version }
66 1     1 1 19 sub keepalive { shift->ws->keepalive(@_) }
67              
68             # ── Query parameter accessors ────────────────────────────────────────
69             # The base Context class has query_string but not parsed query access.
70             # These delegate to PAGI::WebSocket's Hash::MultiValue-based parsing.
71              
72 3     3 1 1097 sub query { shift->ws->query(@_) }
73 1     1 1 12 sub query_params { shift->ws->query_params(@_) }
74 1     1 1 12 sub raw_query { shift->ws->raw_query(@_) }
75 1     1 1 13 sub raw_query_params { shift->ws->raw_query_params(@_) }
76              
77             # ── Header extras ────────────────────────────────────────────────────
78             # Base Context has header() (single value). header_all() returns all
79             # values for multi-value headers like Cookie via Hash::MultiValue.
80              
81 1     1 1 11 sub header_all { shift->ws->header_all(@_) }
82              
83             1;
84              
85             __END__