package Net::Stomp::Frame;
use strict;
use warnings;
our $VERSION='0.61';
use base 'Class::Accessor::Fast';
__PACKAGE__->mk_accessors(qw(command headers body));
BEGIN {
for my $header (
qw(destination exchange content-type content-length message-id reply-to))
{
my $method = $header;
$method =~ s/-/_/g;
no strict 'refs';
*$method = sub {
my $self = shift;
$self->headers->{$header} = shift if @_;
$self->headers->{$header};
};
}
}
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->headers({}) unless defined $self->headers;
return $self;
}
sub as_string {
my $self = shift;
my $command = $self->command;
my $headers = $self->headers;
my $body = $self->body;
my $frame = $command . "\n";
# insert a content-length header
my $bytes_message = 0;
if ( $headers->{bytes_message} ) {
$bytes_message = 1;
delete $headers->{bytes_message};
$headers->{"content-length"} = length( $self->body );
}
while ( my ( $key, $value ) = each %{ $headers || {} } ) {
$frame .= $key . ':' . (defined $value ? $value : '') . "\n";
}
$frame .= "\n";
$frame .= $body || '';
$frame .= "\0";
}
sub parse {
my ($class,$string) = @_;
$string =~ s{
\A\s*
([A-Z]+)\n #command
((?:[^\n]+\n)*)\n # header block
}{}smx;
my ($command,$headers_block) = ($1,$2);
return unless $command;
my ($headers,$body);
if ($headers_block) {
foreach my $line (split(/\n/, $headers_block)) {
my ($key, $value) = split(/\s*:\s*/, $line, 2);
$headers->{$key} = $value;
}
}
if ($headers && $headers->{'content-length'}) {
if (length($string) >= $headers->{'content-length'}) {
$body = substr($string,
0,
$headers->{'content-length'},
'' );
}
else { return } # not enough body
} elsif ($string =~ s/\A(.*?)\0//s) {
# No content-length header.
$body = $1 if length($1);
}
else { return } # no body
return $class->new({
command => $command,
headers => $headers,
body => $body,
});
}
1;
__END__
=head1 NAME
Net::Stomp::Frame - A STOMP Frame
=head1 SYNOPSIS
use Net::Stomp::Frame;
my $frame = Net::Stomp::Frame->new( {
command => $command,
headers => $headers,
body => $body,
} );
my $frame = Net::Stomp::Frame->parse($string);
my $string = $frame->as_string;
=head1 DESCRIPTION
This module encapulates a Stomp frame.
A Stomp frame consists of a command, a series of headers and a body.
For details on the protocol see L<https://stomp.github.io/>.
=head1 METHODS
=head2 new
Create a new L<Net::Stomp::Frame> object:
my $frame = Net::Stomp::Frame->new( {
command => $command,
headers => $headers,
body => $body,
} );
=head2 parse
Create a new L<Net::Somp::Frame> given a string containing the serialised frame:
my $frame = Net::Stomp::Frame->parse($string);
=head2 as_string
Create a string containing the serialised frame representing the frame:
my $string = $frame->as_string;
=head2 command
Get or set the frame command.
=head2 body
Get or set the frame body.
=head2 headers
Get or set the frame headers, as a hashref. All following methods are
just shortcuts into this hashref.
=head2 destination
Get or set the C<destination> header.
=head2 content_type
Get or set the C<content-type> header.
=head2 content_length
Get or set the C<content-length> header.
=head2 exchange
Get or set the C<exchange> header.
=head2 message_id
Get or set the C<message-id> header.
=head2 reply_to
Get or set the C<reply-to> header.
=head1 SEE ALSO
L<Net::Stomp>.
=head1 AUTHOR
Leon Brocard <acme@astray.com>.
=head1 CONTRIBUTORS
Gianni Ceccarelli <dakkar@thenautilus.net>
=head1 COPYRIGHT
Copyright (C) 2006, Leon Brocard
This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.