Merge pull request #1 from jonassmedegaard/master
Adding resource for individual entries. Adding links. Thanks jonassmedegaard.
Naveed Massjouni
12 years ago
18 | 18 | if (not $deployed++) { |
19 | 19 | eval { schema->deploy }; # Fails gracefully if tables already exist. |
20 | 20 | } |
21 | }; | |
22 | ||
23 | get '/feeds/:feed_title/entries/:entry_id' => sub { | |
24 | my $entry_id = 'urn:uuid:' . params->{entry_id}; | |
25 | my $db_entry = schema->resultset('AtomBusEntry')->find({id => $entry_id}); | |
26 | return send_error("No such message exists", 404) | |
27 | unless $db_entry; | |
28 | my $if_none_match = request->header('If-None-Match'); | |
29 | #TODO: support revised entries (i.e. Atompub PUT) | |
30 | # my $revision_id = $db_entry->revision_id || $db_entry->id; | |
31 | my $revision_id = $db_entry->id; | |
32 | ||
33 | # If ETag matches current revision id of entry | |
34 | if (my $id = $if_none_match) { | |
35 | $id =~ s/^"(.*)"$/$1/; # Remove surrounding quotes | |
36 | if ($revision_id eq $id) { | |
37 | status 304; | |
38 | return ''; | |
39 | } | |
40 | } | |
41 | ||
42 | my $entry = _entry_from_db($db_entry); | |
43 | ||
44 | _add_etag($revision_id); | |
45 | header Vary => 'If-None-Match'; | |
46 | ||
47 | return $entry->as_xml; | |
21 | 48 | }; |
22 | 49 | |
23 | 50 | get '/feeds/:feed_title' => sub { |
111 | 138 | updated => $updated, |
112 | 139 | }); |
113 | 140 | $db_feed->update({updated => $updated}); |
114 | _add_etag($db_entry->id); | |
115 | return _entry_from_db($db_entry)->as_xml; | |
141 | $entry = _entry_from_db($db_entry); | |
142 | _add_etag($entry->id); | |
143 | header Location => $entry->link->href; | |
144 | content_type 'application/atom+xml;type=entry'; | |
145 | status 'created'; | |
146 | return $entry->as_xml; | |
116 | 147 | }; |
117 | 148 | |
118 | 149 | sub _gen_id { 'urn:uuid:' . create_UUID_as_string() } |
150 | ||
151 | sub _id_nss { $_ = shift; s/^urn:uuid://; return $_ } | |
119 | 152 | |
120 | 153 | sub _entry_from_db { |
121 | 154 | my $row = shift; |
124 | 157 | $entry->content($row->content); |
125 | 158 | $entry->id($row->id); |
126 | 159 | $entry->updated($row->updated); |
160 | my $self_link = XML::Atom::Link->new; | |
161 | $self_link->rel('self'); | |
162 | $self_link->type('application/atom+xml'); | |
163 | $self_link->href( join( '/', uri_for('/feeds'), $row->feed_title->title, 'entries', _id_nss($row->id) )); | |
164 | $entry->add_link($self_link); | |
127 | 165 | return $entry; |
128 | 166 | } |
129 | 167 |
29 | 29 | }; |
30 | 30 | |
31 | 31 | my $res = dancer_response POST => "/feeds/$feed", { body => $xml1 }; |
32 | is $res->{status} => 200, 'Got 200 for posting entry1.'; | |
32 | is $res->{status} => 201, 'Got 201 for posting entry1.'; | |
33 | 33 | |
34 | 34 | is schema->resultset('AtomBusEntry')->count() => 1, '1 entries in db.'; |
35 | 35 | is schema->resultset('AtomBusFeed')->count() => 1, '1 feed in db.'; |
39 | 39 | ok $entry1, 'Found entry 1.'; |
40 | 40 | |
41 | 41 | $res = dancer_response POST => "/feeds/$feed", { body => $xml2 }; |
42 | is $res->{status} => 200, 'Got 200 for posting entry2.'; | |
42 | is $res->{status} => 201, 'Got 201 for posting entry2.'; | |
43 | 43 | |
44 | 44 | is schema->resultset('AtomBusEntry')->count() => 2, '2 entries in db.'; |
45 | 45 | is schema->resultset('AtomBusFeed')->count() => 1, '1 feed in db.'; |
0 | use Test::More import => ['!pass'], tests => 17; | |
0 | use Test::More import => ['!pass'], tests => 21; | |
1 | 1 | use Dancer qw(:syntax); |
2 | 2 | use Dancer::Test; |
3 | 3 | |
4 | use URI; | |
4 | 5 | use XML::XPath; |
5 | 6 | use Dancer::Plugin::DBIC qw(schema); |
6 | 7 | use AtomBus; |
26 | 27 | response_status_is [ GET => "/feeds/foo" ], 404; |
27 | 28 | }; |
28 | 29 | |
29 | foreach my $i (1 .. 10) { | |
30 | # Create one entry and examine result. | |
31 | my $res = dancer_response POST => "/feeds/foo", { body => sprintf($xml, 1, 1) }; | |
32 | is $res->{status}=> 201, 'Status was 201'; | |
33 | my $etag = new URI($res->{headers}->{etag}, 'urn'); | |
34 | my $location = new URI($res->{headers}->{location}, 'http'); | |
35 | my $id_nss = $location; | |
36 | ($id_nss) =~ s,^.*/,,; | |
37 | is $location->path => "/feeds/foo/entries/$id_nss", 'Location header is well-structured.'; | |
38 | is $etag->as_string => "urn:uuid:$id_nss", 'ETag was contained in location header.'; | |
39 | $res = dancer_response GET => $location->path; | |
40 | is $res->{status}=> 200, 'Entry was GETtable with status 200'; | |
41 | ||
42 | # Create additional entries. | |
43 | foreach my $i (2 .. 10) { | |
30 | 44 | dancer_response POST => "/feeds/foo", { body => sprintf($xml, $i, $i) }; |
31 | 45 | } |
32 | my $res = dancer_response GET => "/feeds/foo"; | |
46 | ||
47 | $res = dancer_response GET => "/feeds/foo"; | |
33 | 48 | my $xp = XML::XPath->new(xml => $res->{content}); |
34 | 49 | my @entries = $xp->findnodes('/feed/entry'); |
35 | 50 | is $res->{status}=> 200, 'Status was 200'; |