Plack::Handler::Stomp - adapt STOMP to (almost) HTTP, via Plack
version 1.15
my $runner = Plack::Handler::Stomp->new({ servers => [ { hostname => 'localhost', port => 61613 } ], subscriptions => [ { destination => '/queue/plack-handler-stomp-test' }, { destination => '/topic/plack-handler-stomp-test', headers => { selector => q{custom_header = '1' or JMSType = 'test_foo'}, }, path_info => '/topic/ch1', }, { destination => '/topic/plack-handler-stomp-test', headers => { selector => q{custom_header = '2' or JMSType = 'test_bar'}, }, path_info => '/topic/ch2', }, ], }); $runner->run(MyApp->get_app());
Sometimes you want to use your very nice web-application-framework dispatcher, module loading mechanisms, etc, but you're not really writing a web application, you're writing a ActiveMQ consumer. In those cases, this module is for you.
This module is inspired by Catalyst::Engine::Stomp, but aims to be usable by any PSGI application.
We consume Net::Stomp::MooseHelpers::CanConnect and Net::Stomp::MooseHelpers::CanSubscribe. Read those modules' documentation to see how to configure servers and subscriptions.
logger
A logger object used by thes handler. Not to be confused by the logger used by the application (either internally, or via a Middleware). Can be any object that can trace, debug, info, warn, error. Defaults to an instance of Log::Any::Proxy. This logger is passed on to the Net::Stomp object held in connection (see Net::Stomp::MooseHelpers::CanConnect).
trace
debug
info
warn
error
connection
destination_path_map
A hashref mapping destinations (queues, topics, subscription ids) to URI paths to send to the application. You should not modify this.
one_shot
If true, exit after the first message is consumed. Useful for testing, defaults to false.
run
Given a PSGI application, loops forever:
connect to a STOMP server (see connect and servers in Net::Stomp::MooseHelpers::CanConnect)
subscribe to whatever needed (see subscribe and subscriptions in Net::Stomp::MooseHelpers::CanSubscribe)
consume STOMP frames in an inner loop (see "frame_loop")
If the application throws an exception, the loop exits re-throwing the exception. If the STOMP connection has problems, the loop is repeated with a different server (see next_server in Net::Stomp::MooseHelpers::CanConnect).
If "one_shot" is set, this function exits after having consumed exactly 1 frame.
frame_loop
Loop forever receiving frames from the STOMP connection. Call "handle_stomp_frame" for each frame.
handle_stomp_frame
Delegates the handling to "handle_stomp_message", "handle_stomp_error", "handle_stomp_receipt", or throws Plack::Handler::Stomp::Exceptions::UnknownFrame if the frame is of some other kind. If you want to handle different kind of frames (maybe because you have some non-standard STOMP server), you can just subclass and add methods; for example, to handle STRANGE frames, add a handle_stomp_strange method.
STRANGE
handle_stomp_strange
handle_stomp_error
Logs the error via the "logger", level warn.
handle_stomp_message
Calls "build_psgi_env" to convert the STOMP message into a PSGI environment.
The environment is then passed to "process_the_message", and the frame is acknowledged.
process_the_message
Runs a PSGI environment through the application, then flattens the response body into a simple string.
The response so flattened is sent back via "maybe_send_reply".
handle_stomp_receipt
Logs (level debug) the receipt id. Nothing else is done with receipts.
maybe_send_reply
Calls "where_should_send_reply" to determine if to send a reply, and where. If it returns a true value, "send_reply" is called to actually send the reply.
where_should_send_reply
Returns the header X-Reply-Address or X-STOMP-Reply-Address from the response.
X-Reply-Address
X-STOMP-Reply-Address
send_reply
Converts the PSGI response into a STOMP frame, by removing the prefix x-stomp- from the key of header fields that have it, removing entirely header fields that don't, and stringifying the body.
x-stomp-
Then sends the frame.
subscribe_single
after modifier on the method provided by Net::Stomp::MooseHelpers::CanSubscribe.
after
It sets the "destination_path_map" to map the destination and the subscription id to the path_info slot of the "subscriptions" element, or to the destination itself if path_info is not defined.
path_info
build_psgi_env
Builds a PSGI environment from the message, like:
# server SERVER_NAME => 'localhost', SERVER_PORT => 0, SERVER_PROTOCOL => 'STOMP', # client REQUEST_METHOD => 'POST', REQUEST_URI => $path_info, SCRIPT_NAME => '', PATH_INFO => $path_info, QUERY_STRING => '', # broker REMOTE_ADDR => $server_hostname, # http HTTP_USER_AGENT => 'Net::Stomp', CONTENT_LENGTH => length($body), CONTENT_TYPE => $content-type, # psgi 'psgi.version' => [1,0], 'psgi.url_scheme' => 'http', 'psgi.multithread' => 0, 'psgi.multiprocess' => 0, 'psgi.run_once' => 0, 'psgi.nonblocking' => 0, 'psgi.streaming' => 1,
In addition, reading from psgi.input will return the message body, and writing to psgi.errors will log via the "logger" at level error.
psgi.input
psgi.errors
Finally, every header in the STOMP message will be available in the "namespace" jms., so for example the message type is in jms.type.
jms.
jms.type
The $path_info is obtained from the "destination_path_map" (i.e. from the path_info subscription options) passed through munge_path_info.
$path_info
You can find examples of use in the tests, or at https://github.com/dakkar/CatalystX-StompSampleApps
Gianni Ceccarelli <gianni.ceccarelli@net-a-porter.com>
This software is copyright (c) 2020 by Net-a-porter.com.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
To install Plack::Handler::Stomp, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Plack::Handler::Stomp
CPAN shell
perl -MCPAN -e shell install Plack::Handler::Stomp
For more information on module installation, please visit the detailed CPAN module installation guide.