Bootylicious
view release on metacpan or search on metacpan
lib/Bootylicious/Plugin/Pingback.pm view on Meta::CPAN
package Bootylicious::Plugin::Pingback;
use strict;
use warnings;
use base 'Mojolicious::Plugin';
use Mojo::DOM;
sub register {
my ($self, $app, $conf) = @_;
$conf ||= {};
$app->routes->route('/pingback')->to(cb => \&_pingback)->name('pingback');
unshift @{$app->renderer->classes}, __PACKAGE__;
$app->plugins->on(
after_dispatch => sub {
my ($c) = @_;
return unless $c->req->method =~ m/GET|HEAD/;
return unless $c->res->code && $c->res->code == 200;
return unless $c->match->endpoint->name eq 'article';
$c->res->headers->header(
'X-Pingback' => $c->url_for('pingback', format => undef)->to_abs);
}
);
}
sub _pingback {
my $self = shift;
my ($source_uri, $target_uri) = _parse_xmlrpc($self);
return _render_bad_request($self) unless $source_uri && $target_uri;
return _render_target_invalid($self)
unless $target_uri =~ m{^/articles/(\d+)/(\d+)/(.*)};
my ($year, $month, $name) = ($1, $2, $3);
$name =~ s/\..*$//;
my $article = $self->get_article($year, $month, $name);
return _render_target_not_found($self) unless $article;
$self->app->log->debug("Fetching $source_uri...");
$self->ua->get(
$source_uri => sub {
my $tx = pop;
$self->app->log->debug("Fetched $source_uri");
return _render_source_not_found($self)
unless $tx->res->code && $tx->res->code == 200;
return _render_source_invalid($self)
unless $tx->res->body =~ m{\Q$target_uri\E};
return _render_pingback_already_registered($self)
if $article->has_pingback($source_uri);
$article->pingback($source_uri);
return _render_success($self);
}
);
}
sub _parse_xmlrpc {
my $self = shift;
return unless $self->req->method eq 'POST' && $self->req->body;
my $dom = Mojo::DOM->new;
$dom = $dom->parse($self->req->body);
my $method = $dom->at('methodCall');
return unless $method;
my $method_name = $method->at('methodName');
return unless $method_name->text eq 'pingback.ping';
( run in 1.346 second using v1.01-cache-2.11-cpan-df04353d9ac )