AtomBus

 view release on metacpan or  search on metacpan

lib/AtomBus.pm  view on Meta::CPAN

package AtomBus;
use Dancer qw(:syntax);
use Dancer::Plugin::DBIC qw(schema);

use Atompub::DateTime qw(datetime);
use UUID::Tiny;
use XML::Atom;
$XML::Atom::DefaultVersion = '1.0';

our $VERSION = '1.0405'; # VERSION

set content_type => 'application/xml';
config->{plugins}{DBIC}{atombus} = config->{atombus}{db};
config->{plugins}{DBIC}{atombus}{schema_class} = 'AtomBus::Schema';
eval { schema->deploy }; # Fails gracefully if tables already exist.

get '/feeds/:feed_title/entries/:entry_id' => sub {
    my $entry_id = 'urn:uuid:' . params->{entry_id};
    my $db_entry = schema->resultset('AtomBusEntry')->find({id => $entry_id});
    return send_error("No such message exists", 404)
        unless $db_entry;
    my $if_none_match = request->header('If-None-Match');
#TODO: support revised entries (i.e. Atompub PUT)
#    my $revision_id = $db_entry->revision_id || $db_entry->id;
    my $revision_id = $db_entry->id;

    # If ETag matches current revision id of entry
    if (my $id = $if_none_match) {
        $id =~ s/^"(.*)"$/$1/; # Remove surrounding quotes
        if ($revision_id eq $id) {
            status 304;
            return '';
        }
    }

    my $entry = _entry_from_db($db_entry);

    _add_etag($revision_id);
    header Vary => 'If-None-Match';

    return $entry->as_xml;
};

get '/feeds/:feed_title' => sub {
    my $feed_title = lc params->{feed_title};
    my $start_after = params->{start_after};
    my $start_at = params->{start_at};
    my $if_none_match = request->header('If-None-Match');
    my $order_id;

    if (my $id = $if_none_match) {
        $id =~ s/^"(.*)"$/$1/; # Remove surrounding quotes
        my $entry = schema->resultset('AtomBusEntry')->find({id => $id});
        $order_id = $entry->order_id if $entry;
    }
    if (my $id = $start_after || $start_at) {
        my $entry = schema->resultset('AtomBusEntry')->find({id => $id});
        return send_error("No such message exists with id $id", 400)
            unless $entry;
        $order_id = $entry->order_id;
    }

    my $db_feed = schema->resultset('AtomBusFeed')->find(
        { title => $feed_title });
    return send_error("No such feed exists named $feed_title", 404)
        unless $db_feed;

    my $feed = XML::Atom::Feed->new;
    $feed->title($feed_title);
    $feed->id($db_feed->id);
    my $person = XML::Atom::Person->new;
    $person->name($db_feed->author_name);
    $feed->author($person);
    $feed->updated($db_feed->updated);
    
    my $self_link = XML::Atom::Link->new;
    $self_link->rel('self');
    $self_link->type('application/atom+xml');
    $self_link->href(request->uri_for(request->path));
    $feed->add_link($self_link);

    #my $hub_link = XML::Atom::Link->new;
    #$hub_link->rel('hub');
    #$hub_link->href('http://184.106.189.98:8080/publish');
    #$feed->add_link($hub_link);

    my %query = (feed_title => $feed_title);
    if ($order_id) {
        $query{order_id} = { '>'  => $order_id } if $if_none_match;
        $query{order_id} = { '>'  => $order_id } if $start_after;
        $query{order_id} = { '>=' => $order_id } if $start_at;
    }
    my $rset = schema->resultset('AtomBusEntry')->search(
        \%query, { order_by => ['order_id'] });
    my $count = config->{atombus}{page_size} || 1000;
    my $last_id;
    while ($count-- && (my $entry = $rset->next)) {
        $feed->add_entry(_entry_from_db($entry));
        $last_id = $entry->id;
    }

    # If ETag was provided and there are no new entries
    if (not $last_id and $if_none_match) {
        status 304;
        return '';
    }

    _add_etag($last_id) if $last_id;
    header Vary => 'If-None-Match';

    return $feed->as_xml;
};

post '/feeds/:feed_title' => sub {
    my $feed_title = lc params->{feed_title};
    my $body = request->body;
    return send_error("Request body is empty", 400)
        unless $body;
    my $entry = XML::Atom::Entry->new(\$body);
    my $updated = datetime->w3cz;
    my $db_feed = schema->resultset('AtomBusFeed')->find_or_create({
        title       => $feed_title,
        id          => _gen_id(),
        author_name => 'AtomBus',
        updated     => $updated,



( run in 2.201 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )