[Rt-commit] [svn] r805 - in rt: . branches/rt-3.3/docs/design_docs branches/rt-3.3/html/REST/2.0 branches/rt-3.3/html/REST/2.0/Create branches/rt-3.3/html/REST/2.0/Delete branches/rt-3.3/html/REST/2.0/Describe branches/rt-3.3/html/REST/2.0/Elements branches/rt-3.3/html/REST/2.0/Get branches/rt-3.3/html/REST/2.0/NoAuth branches/rt-3.3/html/REST/2.0/Put branches/rt-3.3/html/REST/2.0/Search branches/rt-3.3/html/REST/2.0/Update

autrijus at pallas.eruditorum.org autrijus at pallas.eruditorum.org
Sun May 2 14:03:32 EDT 2004


Author: autrijus
Date: Sun May  2 14:03:32 2004
New Revision: 805

Added:
   rt/branches/rt-3.3/docs/design_docs/atom-api.txt
   rt/branches/rt-3.3/html/REST/2.0/Create/index
   rt/branches/rt-3.3/html/REST/2.0/Delete/index
   rt/branches/rt-3.3/html/REST/2.0/Describe/
   rt/branches/rt-3.3/html/REST/2.0/Describe/index
   rt/branches/rt-3.3/html/REST/2.0/Get/index
   rt/branches/rt-3.3/html/REST/2.0/Put/
   rt/branches/rt-3.3/html/REST/2.0/Put/index
   rt/branches/rt-3.3/html/REST/2.0/Update/index
Modified:
   rt/   (props changed)
   rt/branches/rt-3.3/html/REST/2.0/Elements/Link
   rt/branches/rt-3.3/html/REST/2.0/NoAuth/feed.css
   rt/branches/rt-3.3/html/REST/2.0/Search/index
   rt/branches/rt-3.3/html/REST/2.0/dhandler
   rt/branches/rt-3.3/html/REST/2.0/index
Log:
 ----------------------------------------------------------------------
 r4382 at not:  autrijus | 2004-05-02T18:02:39.870947Z
 
 * Describes RT/REST 2.0, Atom-compatible API.
 ----------------------------------------------------------------------
 r4383 at not:  autrijus | 2004-05-02T18:03:08.473736Z
 
 * Put stubs to all the unimplemented verbs.
 ----------------------------------------------------------------------


Added: rt/branches/rt-3.3/docs/design_docs/atom-api.txt
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.3/docs/design_docs/atom-api.txt	Sun May  2 14:03:32 2004
@@ -0,0 +1,67 @@
+RT/REST API 2.0
+===============
+This implementation is based on Atom 0.3.
+
+"FeedURI", "EditURI" and "PostURI" are specified here:
+    http://www.atomenabled.org/developers/api/atom-api-spec.php
+
+"AtomFeed" and "AtomEntry" are specified here:
+    http://www.atomenabled.org/developers/syndication/atom-format-spec.php
+
+Request methods and response status codes are specified here:
+    http://www.w3.org/Protocols/rfc2616/rfc2616.html
+
+Some example URIs are:
+
+    /REST/2.0/				# FeedURI
+    /REST/2.0/tickets			# FeedURI
+    /REST/2.0/tickets-new		# PostURI (Container)
+    /REST/2.0/tickets/15		# EditURI
+    /REST/2.0/tickets/15-comment	# PostURI (Object)
+    /REST/2.0/tickets/15-correspond	# PostURI (Object)
+    /REST/2.0/tickets/15/transactions	# FeedURI
+
+[GET FeedURI]
+Search for objects within an container.
+Possible query parameters: rows, page, query.
+200: Success.  Body is the result, serialized as an AtomFeed.
+400: Request failed.  Body is error message in text/plain.
+404: There is no container matching the specified URI.
+
+[GET EditURI]
+Get a representation of an object.
+200: Success.  Body is the object, serialized as an AtomEntry.
+400: Request failed.  Body is error message in text/plain.
+404: There is no object matching the specified URI.
+
+[PUT EditURI]
+Modifies an object with the AtomEntry in the request body.
+200: Success.  Body is the object, serialized as an AtomEntry.
+400: Request failed.  Body is error message in text/plain.
+404: There is no object matching the specified URI.
+
+[DELETE EditURI]
+Delete an object.
+200: Successfully deleted.  Body is success message in text/plain.
+400: Request failed.  Body is error message in text/plain.
+404: There is no object matching the specified URI.
+
+[OPTIONS PostURI], [GET PostURI]
+On a container, returns the schema of objects acceptable by this container.
+On an object, returns the schema acceptable by the specified 'adverb'.
+200: Success.  Body is schema in a format determined by content negotiation.
+400: Request failed.  Body is error message in text/plain.
+404: There is no container matching the specified URI.
+
+[POST PostURI] (Container)
+Create a new object from the AtomEntry in the request's body.
+303: Created.  The 'Location:' header is set to the new object's EditURI
+     (for subsequent Get/Update).  Body is success message in text/plain.
+400: Request failed.  Body is error message in text/plain.
+404: There is no container matching the specified URI.
+
+[POST PostURI] (Object)
+Updates an object, using an 'adverb' acceptable to that object's class.
+200: Success.  Body is the object, serialized as an AtomEntry.
+400: Request failed.  Body is error message in text/plain.
+404: The specific object does not exist, or does not support this adverb.

Added: rt/branches/rt-3.3/html/REST/2.0/Create/index
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.3/html/REST/2.0/Create/index	Sun May  2 14:03:32 2004
@@ -0,0 +1,6 @@
+%# [POST PostURI] (Container)
+%# Create a new object from the AtomEntry in the request's body.
+%# 303: Created.  The 'Location:' header is set to the new object's EditURI
+%#      (for subsequent Get/Update).  Body is success message in text/plain.
+%# 400: Request failed.  Body is error message in text/plain.
+%# 404: There is no container matching the specified URI.

Added: rt/branches/rt-3.3/html/REST/2.0/Delete/index
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.3/html/REST/2.0/Delete/index	Sun May  2 14:03:32 2004
@@ -0,0 +1,5 @@
+%# [DELETE EditURI]
+%# Delete an object.
+%# 200: Successfully deleted.  Body is success message in text/plain.
+%# 400: Request failed.  Body is error message in text/plain.
+%# 404: There is no object matching the specified URI.

Added: rt/branches/rt-3.3/html/REST/2.0/Describe/index
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.3/html/REST/2.0/Describe/index	Sun May  2 14:03:32 2004
@@ -0,0 +1,6 @@
+%# [OPTIONS PostURI], [GET PostURI]
+%# On a container, returns the schema of objects acceptable by this container.
+%# On an object, returns the schema acceptable by the specified 'adverb'.
+%# 200: Success.  Body is schema in a format determined by content negotiation.
+%# 400: Request failed.  Body is error message in text/plain.
+%# 404: There is no container matching the specified URI.

Modified: rt/branches/rt-3.3/html/REST/2.0/Elements/Link
==============================================================================
--- rt/branches/rt-3.3/html/REST/2.0/Elements/Link	(original)
+++ rt/branches/rt-3.3/html/REST/2.0/Elements/Link	Sun May  2 14:03:32 2004
@@ -1,18 +1,31 @@
 %# Make a HTML link and an Atom link
 <link rel="<% $Relation %>" type="<% $Type %>" href="<% $URI %>" title="<% $Title %>" />
-<a class="<% $class %>" rel="<% $Relation %>" type="<% $Type %>" href="<% $URI %>" title="<% $Title %>" xmlns="http://www.w3.org/1999/xhtml"><% loc($TextMap{$Relation}) || $Title %></a>
+<a accesskey="<% $accesskey %>" class="<% $class %>" rel="<% $Relation %>" type="<% $Type %>" href="<% $URI %>" title="<% $Title %>" xmlns="http://www.w3.org/1999/xhtml"><% loc($TextMap{$Relation}) || $Title %></a>
 <%INIT>
 my %TextMap = (
     'alternate'	    => 'HTML',	# loc
-    'service.post'  => 'Post',	# loc
+    'service.post'  => 'Create',# loc
     'service.feed'  => 'Index',	# loc
     'service.edit'  => 'Edit',	# loc
 );
 my $class = lc($TextMap{$Relation} || 'nav');
+my %KeyMap = (
+    'alternate'	    => 'h',
+    'next'	    => 'n',
+    'prev'	    => 'p',
+    'service.post'  => 'c',
+    'service.feed'  => 'i',
+);
+my $accesskey = $KeyMap{$Relation};
+if ($IsEntry) {
+    $accesskey = ($m->notes('EntryAccessKey') + 1) % 10;
+    $m->notes(EntryAccessKey => $accesskey);
+}
 </%INIT>
 <%ARGS>
 $Relation => "alternate"
 $Type => "application/x.atom+xml"
 $URI => "#"
 $Title => ""
+$IsEntry => 0
 </%ARGS>

Added: rt/branches/rt-3.3/html/REST/2.0/Get/index
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.3/html/REST/2.0/Get/index	Sun May  2 14:03:32 2004
@@ -0,0 +1,5 @@
+%# [GET EditURI]
+%# Get a representation of an object.
+%# 200: Success.  Body is the object, serialized as an AtomEntry.
+%# 400: Request failed.  Body is error message in text/plain.
+%# 404: There is no object matching the specified URI.

Modified: rt/branches/rt-3.3/html/REST/2.0/NoAuth/feed.css
==============================================================================
--- rt/branches/rt-3.3/html/REST/2.0/NoAuth/feed.css	(original)
+++ rt/branches/rt-3.3/html/REST/2.0/NoAuth/feed.css	Sun May  2 14:03:32 2004
@@ -53,7 +53,7 @@
   color: #ccccff;
 }
 
-a.post {
+a.create {
   background-color: #66ee66;
   font-weight: bold;
 }

Added: rt/branches/rt-3.3/html/REST/2.0/Put/index
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.3/html/REST/2.0/Put/index	Sun May  2 14:03:32 2004
@@ -0,0 +1,5 @@
+%# [PUT EditURI]
+%# Modifies an object with the AtomEntry in the request body.
+%# 200: Success.  Body is the object, serialized as an AtomEntry.
+%# 400: Request failed.  Body is error message in text/plain.
+%# 404: There is no object matching the specified URI.

Modified: rt/branches/rt-3.3/html/REST/2.0/Search/index
==============================================================================
--- rt/branches/rt-3.3/html/REST/2.0/Search/index	(original)
+++ rt/branches/rt-3.3/html/REST/2.0/Search/index	Sun May  2 14:03:32 2004
@@ -1,4 +1,9 @@
-%# Search, aka FeedURI
+%# [GET FeedURI]
+%# Search for objects within an container.
+%# Possible query parameters: rows, page, query.
+%# 200: Success.  Body is the result, serialized as an AtomFeed.
+%# 400: Request failed.  Body is error message in text/plain.
+%# 404: There is no container matching the specified URI.
 <?xml version="1.0" encoding="utf-8"?>
 <?xml-stylesheet type="text/css" href="<% $BaseURI %>/NoAuth/feed.css"?>
 <feed version="0.3" xmlns="http://purl.org/atom/ns#">
@@ -12,7 +17,7 @@
     (<&|/l, $TotalFound&>[_1] Total</&>)
   </tagline>
   <& $Link, Relation => "service.feed", URI => $BaseURI, Title => loc("Homepage") &>
-  <& $Link, Relation => "service.post", URI => "$FeedURI.new", Title => loc("Create"). ": ". loc($Type) &>
+  <& $Link, Relation => "service.post", URI => "$FeedURI-new", Title => loc("Create"). ": ". loc($Type) &>
 %# XXX - The URI below is incorrect; should point to collection URL
   <& $Link, Type => 'text/html', URI => $RT::WebURL, Title => loc($Type) &>
   <modified><% $Now->W3CDTF %></modified>
@@ -20,7 +25,7 @@
 % foreach my $entry (@entries) {
   <entry>
     <title mode="escaped"><% $entry->{Name} || "#$entry->{Id}" %></title>
-    <& $Link, Relation => "service.edit", URI => "$FeedURI/$entry->{Id}", Title => loc("Edit"). ": $entry->{Name}" &>
+    <& $Link, Relation => "service.edit", URI => "$FeedURI/$entry->{Id}", Title => loc("Edit"). ": $entry->{Name}", IsEntry => 1 &>
     <summary mode="escaped"><% $entry->{Description} %></summary>
     <modified><% $entry->{LastUpdated} %></modified>
     <issued><% $entry->{Created} %></issued>

Added: rt/branches/rt-3.3/html/REST/2.0/Update/index
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.3/html/REST/2.0/Update/index	Sun May  2 14:03:32 2004
@@ -0,0 +1,5 @@
+%# [POST PostURI] (Object)
+%# Updates an object, using an 'adverb' acceptable to that object's class.
+%# 200: Success.  Body is the object, serialized as an AtomEntry.
+%# 400: Request failed.  Body is error message in text/plain.
+%# 404: The specific object does not exist, or does not support this adverb.

Modified: rt/branches/rt-3.3/html/REST/2.0/dhandler
==============================================================================
--- rt/branches/rt-3.3/html/REST/2.0/dhandler	(original)
+++ rt/branches/rt-3.3/html/REST/2.0/dhandler	Sun May  2 14:03:32 2004
@@ -133,16 +133,41 @@
 
 $session{CurrentUser} = $CurrentUser;
 
+my $verb = {
+    GET	    => 'Get',
+    HEAD    => 'Get',
+    POST    => 'Create',
+    PUT	    => 'Put',
+    DELETE  => 'Delete',
+    OPTIONS => 'Describe',
+}->{$r->method} or return $m->comp('Elements/Error', Status => 405);
+
 my $path = $m->dhandler_arg;
-my $type = $path;
-$type =~ s{/.*}{};
-$type =~ s{-}{/};
+my ($type, @parts) = grep length, split('/', $path);
+
 if ($type ne lc($type)) {
     $path =~ s{([^/]*)}{\L$type};
     $r->header_out(Location => $path);
     return $m->comp('Elements/Error', Status => 301);
 }
 
+my $adverb = '';
+if ($type =~ s/-(\w+)$//) {
+    $adverb = $1;
+    $verb = 'Describe' if $verb eq 'Get';
+    $m->comp('Elements/Error', Status => 405)
+        unless $verb =~ /Create|Describe/;
+}
+
+if ((@parts % 2) == 0) {
+    # FeedURI on collection
+    $verb = 'Search' if $verb eq 'Get';
+}
+elsif ($adverb) {
+    # PostURI on object
+    $verb = 'Update' if $verb eq 'Create';
+}
+
 my $map = $m->comp('Elements/Introspect', Want => 'CollectionToClass');
 my $class = $map->{$type};
 if ($class) {
@@ -184,8 +209,9 @@
 }
 
 $m->comp(
-    'Search/index', %ARGS,
+    "$verb/index", %ARGS,
     Type => $type,
+    Adverb => $adverb,
     CollectionClass => $class,
     FeedURI => "$BaseURI/\L$type",
 );

Modified: rt/branches/rt-3.3/html/REST/2.0/index
==============================================================================
--- rt/branches/rt-3.3/html/REST/2.0/index	(original)
+++ rt/branches/rt-3.3/html/REST/2.0/index	Sun May  2 14:03:32 2004
@@ -9,8 +9,8 @@
   </author>
   <& $Link, Type => 'text/html', URI => $RT::WebURL, Title => loc("Homepage") &>
 % foreach my $type (@{$m->comp('Elements/Introspect', Want => 'TopLevelCollections')}) {
-  <& $Link, Relation => 'service.feed', URI => "$BaseURI/\L$type", Title => loc($type) &>
-  <& $Link, Relation => 'service.post', URI => "$BaseURI/\L$type.new", Title => loc("Create") . ": " . loc($type) &>
+  <& $Link, Relation => 'service.feed', URI => "$BaseURI/\L$type", Title => loc($type), IsEntry => 1 &>
+  <& $Link, Relation => 'service.post', URI => "$BaseURI/\L$type-new", Title => loc("Create") . ": " . loc($type) &>
 % }
   <modified><% $Now->W3CDTF %></modified>
   <generator url="http://www.bestpractical.com/rt/" version="<% $RT::VERSION %>">RT</generator>


More information about the Rt-commit mailing list