File Coverage

blib/lib/Mojo/SSE.pm
Criterion Covered Total %
statement 35 35 100.0
branch 20 22 90.9
condition 3 4 75.0
subroutine 6 6 100.0
pod 2 2 100.0
total 66 69 95.6


line stmt bran cond sub pod time code
1             package Mojo::SSE;
2 65     65   131529 use Mojo::Base -strict;
  65         173  
  65         539  
3              
4 65     65   517 use Carp qw(croak);
  65         189  
  65         4949  
5 65     65   498 use Exporter qw(import);
  65         206  
  65         3503  
6 65     65   1176 use Mojo::Util qw(decode encode);
  65         208  
  65         78233  
7              
8             our @EXPORT_OK = (qw(build_event parse_event));
9              
10             my $SPLIT_RE = qr/(?:\x0d\x0a|(?
11              
12             sub build_event {
13 63     63 1 190708 my $event = shift;
14              
15 63 100       877 my @data = defined $event->{text} ? split($SPLIT_RE, $event->{text}) : ();
16 63 100       244 my @comment = defined $event->{comment} ? split($SPLIT_RE, $event->{comment}) : ();
17              
18 63         113 my @parts;
19 63 100       139 if (@comment) { push @parts, ": $_" for @comment }
  2         11  
20             else {
21 61 100       215 push @parts, "event: $event->{type}" if defined $event->{type};
22 61         292 push @parts, "data: $_" for @data;
23 61 100       218 push @parts, "id: $event->{id}" if defined $event->{id};
24             }
25              
26 63         388 return encode('UTF-8', join("\x0d\x0a", @parts, '', ''));
27             }
28              
29             sub parse_event {
30 103     103 1 69693 my $buffer = shift;
31 103         492 my $event = {id => undef, type => 'message', text => ''};
32              
33 103         1218 while ($$buffer =~ s/^(.*?)(?:(?:\x0d\x0a|(?
34              
35             # Skip lines with encoding errors
36 77 50       316 next unless defined(my $lines = decode 'UTF-8', $1);
37              
38             # Skip comments
39 77 100       560 next if $lines =~ /^\s*:/;
40              
41 74         188 my $first = 0;
42 74         1050 for my $line (split $SPLIT_RE, $lines) {
43 113 100 50     689 if ($line =~ /^event(?::\s*(\S.*))?$/) { $event->{type} = $1 // 'message' }
  15 100       94  
    50          
44 81 100 100     513 elsif ($line =~ /^data(?::\s*(.*))?$/) { $event->{text} .= ($first++ ? "\n" : '') . ($1 // '') }
45 17         64 elsif ($line =~ /^id(?::\s*(.*))?$/) { $event->{id} = $1 }
46             }
47              
48 74         316 return $event;
49             }
50              
51 29         160 return undef;
52             }
53              
54             1;
55              
56             =encoding utf8
57              
58             =head1 NAME
59              
60             Mojo::SSE - Server-Sent Events
61              
62             =head1 SYNOPSIS
63              
64             use Mojo::SSE qw(build_event parse_event);
65              
66             =head1 DESCRIPTION
67              
68             L implements the Server-Sent Events protocol. Note that this module is B and may change
69             without warning!
70              
71             =head1 FUNCTIONS
72              
73             L implements the following functions, which can be imported individually.
74              
75             =head2 build_event
76              
77             my $bytes = build_event $event, $chars;
78              
79             Build Server-Sent Event.
80              
81             =head2 parse_event
82              
83             my $event = parse_event \$bytes;
84              
85             Parse Server-Sent Event. Returns C if no complete event was found.
86              
87             =head1 SEE ALSO
88              
89             L, L, L.
90              
91             =cut