[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