NAME
Mojolicious::Plugin::PubSubHubbub - Publish and Subscribe with PubSubHubbub
SYNOPSIS
# Mojolicious
$app->plugin(PubSubHubbub => {
hub => 'https://hub.example.org/',
pubsub_verify => sub {
return 1;
}
});
my $r = $app->routes;
$r->route('/:user/callback_url')->pubsub;
# Mojolicious::Lite
plugin 'PubSubHubbub' => {
hub => 'https://hub.example.org'
};
any('/:user/callback_url')->pubsub;
# In Controllers:
# Publish feeds to subscribers
$c->pubsub->publish(
'https://sojolicious.example/blog.atom',
'https://sojolicious.example/activity.atom'
);
# Subscribe to a feed
$c->pubsub->subscribe(
topic => 'https://sojolicious.example/feed.atom',
hub => 'https://hub.sojolicious.example'
);
# Discover a resource
my ($topic, $hub) = $c->pubsub->discover('http://sojolicious.example/');
if ($topic && $hub) {
$c->pubsub->subscribe( topic => $topic, hub => $hub );
};
# Unsubscribe from a feed
$c->pubsub->unsubscribe(
topic => 'https://sojolicious.example/feed.atom',
hub => 'https://hub.sojolicious.example'
);
DESCRIPTION
Mojolicious::Plugin::PubSubHubbub is a plugin to publish and subscribe to PubSubHubbub 0.3 Webhooks.
The plugin currently supports the publisher and subscriber part of the protocol, not the hub part.
This plugin is data store agnostic. Please use this plugin by applying hooks and callbacks.
This module is an early release! There may be significant changes in the future.
ATTRIBUTES
hub
$ps->hub('http://pubsubhubbub.appspot.com/');
my $hub = $ps->hub;
The preferred hub. Currently local hubs are not supported. Establishes an endpoint called pubsub-hub
.
Defaults to pubsubhubbub.appspot.com, but this may change without notification.
lease_seconds
my $seconds = $ps->lease_seconds;
$ps->lease_seconds(100 * 24 * 60 * 60);
Seconds a subscription is valid by default before auto refresh is enabled. You can not rely on auto refresh by the hub - your subscriber should resubscribe automatically, if the hub does not ask for renewal.
Defaults to 9 days.
METHODS
register
# Mojolicious
$app->plugin(PubSubHubbub => {
hub => 'https://hub.example.org/',
lease_seconds => 100 * 24 * 60 * 60
});
# Mojolicious::Lite
plugin 'PubSubHubbub' => {
hub => 'https://hub.example.org/',
lease_seconds => 100 * 24 * 60 * 60
};
# Or in your config file
{
PubSubHubbub => {
hub => 'https://hub.example.org/',
lease_seconds => 100 * 24 * 60 * 60
}
}
Called when registering the plugin. Accepts the attributes mentioned as parameters.
All parameters can be set either as part of the configuration file with the key PubSubHubbub
or on registration (that can be overwritten by configuration).
SHORTCUTS
pubsub
# Mojolicious
my $r = $app->routes;
$r->route('/callback_url')->pubsub;
# Mojolicious::Lite
any('/callback_url')->pubsub;
Define the callback endpoint for your subscriptions. Establishes an endpoint called pubsub-callback
.
HELPERS
pubsub->discover
# In Controllers
my ($topic, $hub) = $c->pubsub->discover('http://sojolicious.example/');
Discover a topic feed and a hub based on a URI. The discovery heuristics may change without notification.
pubsub->publish
# In Controllers
my $success = $c->pubsub->publish(
'my_feed', # named route
'/feed.atom', # relative paths
'https://sojolicious.example/feed.atom' # absolute URIs
);
Publish a list of feeds in terms of a notification to the hub. Supports endpoints, named routes, relative paths and absolute URIs. Returns a true value on success.
pubsub->subscribe
# In Controllers
if ($c->pubsub->subscribe(
topic => 'https://sojolicious.example/feed.atom',
hub => 'https://hub.sojolicious.example',
lease_seconds => 123456
)) {
print 'You successfully subscribed!';
};
Subscribe to a topic.
Relevant parameters are hub
, lease_seconds
, secret
, verify_token
, and callback
. Additional parameters are ignored but can be accessed in the hooks. If no verify_token
is given, it is automatically generated. If no callback
is given, the route callback is used. If no lease_seconds
is given, the subscription won't automatically terminate. If a secret
is given, it must be unique for every callback
and hub
combination to allow for bulk distribution.
The method returns a true
value on success and a false
value if an error occured. If called in an array context, the hub's response message body is returned additionally.
pubsub->unsubscribe
# In Controllers
if ($c->pubsub->unsubscribe(
topic => 'https://sojolicious.example/feed.atom',
hub => 'https://hub.sojolicious.example'
)) {
print 'You successfully unsubscribed!';
};
Unsubscribe from a topic.
Relevant parameters are hub
, secret
, verify_token
, and callback
. Additional parameters are ignored but can be accessed in the hooks. If no verify_token
is given, it is automatically generated. If no callback
is given, the route callback is used.
The method returns a true
value on success and a false
value if an error occured. If called in an array context, the hub's response message body is returned additionally.
CALLBACKS
pubsub_accept
# Establish callback
$app->callback(
pubsub_accept => sub {
my ($c, $type, $topics) = @_;
# Filter topics
my @new_topics = grep($_ !~ /catz/, @$topics);
# Set secret
my $secret = 'z0idberg';
# Set X-Hub-On-Behalf-Of value
my $on_behalf = 3;
return (\@new_topics, $secret, $on_behalf);
});
This callback is released, when content arrives at the pubsub endpoint. The parameters passed to the callback include the current controller object, the content type, and an array reference of topics.
Expects an array reference of maybe filtered topics, a secret if necessary, and the value of X-Hub-On-Behalf-Of
. If the returned topic list is empty, the processing will stop. If the callback is not established, the complete content will be processed.
The callback can be established with the callback helper or on registration.
pubsub_verify
# Establish callback
$app->callback(
pubsub_verify => sub {
my ($c, $param) = @_;
# Topic is valid
if ($param->{topic} =~ /catz/ &&
$param->{verify_token} eq 'zoidberg') {
return 1;
};
# Not verified
return;
});
This callback is released, when a verification is requested. The parameters include the current controller object and the parameters of the verification request as a hash reference (without hub.
-prefix). If verification is granted, this callback must return a true value.
The callback can be established with the callback helper or on registration.
HOOKS
on_pubsub_content
$app->hook(
on_pubsub_content => sub {
my ($c, $type, $dom) = @_;
if ($type eq 'atom') {
$dom->find('entry')->each(
print $_->at('title')->text, "\n";
);
};
return;
});
This hook is released, when desired (i.e., verified and optionally filtered) content arrives. The parameters include the current controller object, the content type (either atom
or rss
), and the - maybe topic filtered - content as a Mojo::DOM object.
The Mojo::DOM object is canonicalized in a way that each entry in the feed (either RSS or Atom) includes its topic in the href
of source > link[rel="self"]
.
before_pubsub_subscribe
$app->hook(
before_pubsub_subscribe => sub {
my ($c, $params, $post) = @_;
my $topic = $params->{topic};
print "Start following $topic\n";
return;
});
This hook is released, before a subscription request is sent to a hub. The parameters include the current controller object, the parameters prepared for subscription as a hash reference and the POST
string as a string reference. This hook can be used to store subscription information and establish a secret.
after_pubsub_subscribe
$app->hook(
after_pubsub_subscribe => sub {
my ($c, $hub, $params, $status, $body) = @_;
if ($status !~ /^2/) {
warn 'Error: ', $body;
};
return;
});
This hook is released, after a subscription request is sent to a hub and the response is processed. The parameters include the current controller object, the hub location, the parameters sent for subscription as a hash reference, the response status, and the response body. This hook can be used to deal with errors.
before_pubsub_unsubscribe
$app->hook(
before_pubsub_unsubscribe => sub {
my ($c, $params, $post) = @_;
my $topic = $params->{topic};
print "Stop following $topic\n";
return;
});
This hook is released, before an unsubscription request is sent to a hub. The parameters include the current controller object, the parameters prepared for unsubscription as a hash reference and the POST
string as a string reference. This hook can be used to store unsubscription information.
after_pubsub_unsubscribe
$app->hook(
after_pubsub_unsubscribe => sub {
my ($c, $hub, $params, $status, $body) = @_;
if ($status !~ /^2/) {
warn 'Error: ', $body;
};
return;
});
This hook is released, after an unsubscription request is sent to a hub and the response is processed. The parameters include the current controller object, the hub location, the parameters sent for unsubscription as a hash reference, the response status, and the response body. This hook can be used to deal with errors.
EXAMPLE
The examples/
folder contains a full working example application with publishing, subscription and discovery logic. The example has additional dependencies of DBI, DBD::SQLite and XML::Loy (at least v0.13).
It can be started using the daemon, morbo or hypnotoad, and needs to be accessible from the web.
$ perl examples/pubsubapp daemon
This example may be a good starting point for your own implementation, especially, if you deal with the subscriber part.
TODO
Currently all methods are blocking. In an upcoming release all blocking methods will allow for non-blocking as well.
DEPENDENCIES
Mojolicious (best with SSL support), Mojolicious::Plugin::Util::Endpoint, Mojolicious::Plugin::Util::Callback, Mojolicious::Plugin::Util::RandomString.
AVAILABILITY
https://github.com/Akron/Mojolicious-Plugin-PubSubHubbub
COPYRIGHT AND LICENSE
Copyright (C) 2011-2021, Nils Diewald.
This program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version 2.0.