[Rt-commit] [svn] r804 - in rt: . branches/rt-3.3/html/REST/2.0 branches/rt-3.3/html/REST/2.0/Elements branches/rt-3.3/html/REST/2.0/Error branches/rt-3.3/html/REST/2.0/Search

autrijus at pallas.eruditorum.org autrijus at pallas.eruditorum.org
Sun May 2 11:58:17 EDT 2004


Author: autrijus
Date: Sun May  2 11:58:17 2004
New Revision: 804

Added:
   rt/branches/rt-3.3/html/REST/2.0/Elements/Error
   rt/branches/rt-3.3/html/REST/2.0/Elements/Introspect
Removed:
   rt/branches/rt-3.3/html/REST/2.0/Error/
Modified:
   rt/   (props changed)
   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:
 ----------------------------------------------------------------------
 r4379 at not:  autrijus | 2004-05-02T15:26:00.873038Z
 
 * Do content negotiation with the browser and fallback on text/xml.
 * Clean up namespaces a little.
 ----------------------------------------------------------------------
 r4380 at not:  autrijus | 2004-05-02T15:58:03.262688Z
 
 * Move Error/index to Elements/Error since Error is not a verb.
 * Refactor the Introspect part away to Elements/.
 * Correctly redirects /Templates/ and /template/ to /templates/.
 
 ----------------------------------------------------------------------


Added: rt/branches/rt-3.3/html/REST/2.0/Elements/Error
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.3/html/REST/2.0/Elements/Error	Sun May  2 11:58:17 2004
@@ -0,0 +1,8 @@
+<%INIT>
+$r->content_type('text/html');
+$r->status($Status);
+$m->abort($Status) unless $ENV{FCGI_ROLE};
+</%INIT>
+<%ARGS>
+$Status => 500
+</%ARGS>

Added: rt/branches/rt-3.3/html/REST/2.0/Elements/Introspect
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.3/html/REST/2.0/Elements/Introspect	Sun May  2 11:58:17 2004
@@ -0,0 +1,50 @@
+<%INIT>
+my %collection_to_obj;
+my %collection_to_class;
+my %record_to_collection;
+foreach my $key (keys %INC) {
+    $key =~ m{^(RTx?(?:/.+)?/([^_/]+)).pm$}i or next;
+    my ($class, $type) = ($1, $2);
+    $class =~ s{/}{::}g;
+    $class->can('NewItem') or next;
+    my $obj = eval {$class->new($session{CurrentUser})->NewItem} or next;
+    $collection_to_obj{$type} = $obj;
+    $collection_to_class{$type} = $class;
+    $record_to_collection{$1} = $type if ref($obj) =~ /(\w+)$/;
+}
+
+my @collection = sort keys %collection_to_obj;
+my @record = (
+    map {($_, $_."Id")} (qw(Member PrincipalType Object),
+    sort keys %record_to_collection)
+);
+
+my %gone;
+foreach my $type (@collection) {
+    my $obj = $collection_to_obj{$type} or next;
+
+    # First, eliminate collections that can be inferred from other objects
+    foreach my $method (@collection) {
+	$gone{$method}++ if $obj->can($method) or $obj->can("_$method");
+    }
+
+    # Next, eliminate normalization records with multiple parent fields 
+    my $score = 0;
+    foreach my $property (@record) {
+	$score++ if $obj->_Accessible($property, 'read');
+    }
+    $gone{$type}++ if $score > 1;
+}
+
+delete @collection_to_class{keys %gone};
+return {map {(lc($_) => $collection_to_class{$_})} keys %collection_to_class}
+    if $Want eq 'CollectionToClass';
+return {map {(lc($_) => $record_to_collection{$_})} keys %record_to_collection}
+    if $Want eq 'RecordToCollection';
+
+delete @collection_to_obj{keys %gone};
+return [sort keys %collection_to_obj];
+</%INIT>
+<%ARGS>
+$Want
+</%ARGS>

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 11:58:17 2004
@@ -20,12 +20,12 @@
 % 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}" &>
     <summary mode="escaped"><% $entry->{Description} %></summary>
     <modified><% $entry->{LastUpdated} %></modified>
     <issued><% $entry->{Created} %></issued>
     <created><% $entry->{Created} %></created>
     <id><% $entry->{URI} %></id>
-    <& $Link, Relation => "service.edit", URI => "$FeedURI/$entry->{Id}", Title => loc("Edit"). ": $entry->{Name}" &>
 % if ($entry->{HTML_URL}) {
     <& $Link, Type => 'text/html', URI => "$RT::WebURL$entry->{HTML_URL}", Title => $entry->{Name} &>
 % }

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 11:58:17 2004
@@ -12,7 +12,9 @@
 my $nonce = Digest::MD5::md5_hex($realm . rand());
 my %methods = map {($_ => 1)} @RT::RESTAuthenticationMethods;
 
-my $atom_client = ($r->header_in('User-Agent') =~ /\batom\b/i);
+my %accept = map { $_ => 1 } $r->header_in('Accept') =~ m{([^\s,]+/[^;,]+)}g;
+my $atom_client = $accept{'application/x.atom+xml'};
+
 my $header_out = sub {
     $ENV{FCGI_ROLE} ? $r->header_out(@_) : $r->headers_out->add(@_);
 };
@@ -126,25 +128,33 @@
 }
 
 if (!$CurrentUser or !$CurrentUser->Id) {
-    return $m->comp('Error/index', Status => 401);
+    return $m->comp('Elements/Error', Status => 401);
 }
 
 $session{CurrentUser} = $CurrentUser;
 
-# TODO: Redirect /template to /templates
-
 my $path = $m->dhandler_arg;
-my $type = lc($path);
+my $type = $path;
 $type =~ s{/.*}{};
 $type =~ s{-}{/};
-
-my $class;
-foreach my $key (keys %INC) {
-    $key =~ m{^(RTx?(?:/.+)?/($type)).pm$}i or next;
-    ($class, $type) = ($1, $2);
-    $class =~ s{/}{::}g;
-    $class->can('UnLimit') or (undef $class, next);
-    last;
+if ($type ne lc($type)) {
+    $path =~ s{([^/]*)}{\L$type};
+    $r->header_out(Location => $path);
+    return $m->comp('Elements/Error', Status => 301);
+}
+
+my $map = $m->comp('Elements/Introspect', Want => 'CollectionToClass');
+my $class = $map->{$type};
+if ($class) {
+    $type = $1 if $class =~ m/([^:]+)$/;
+}
+else {
+    $map = $m->comp('Elements/Introspect', Want => 'RecordToCollection');
+    if (my $new_type = lc($map->{$type})) {
+	$path =~ s{([^/]*)}{$new_type};
+	$r->header_out(Location => $path);
+	return $m->comp('Elements/Error', Status => 301);
+    }
 }
 
 my $BaseURI = "$RT::WebPath/REST/2.0";
@@ -154,11 +164,23 @@
 $ARGS{Now} = RT::Date->new($session{CurrentUser});
 $ARGS{Now}->SetToNow;
 
-$r->content_type('text/xml; charset=utf-8');
+my @types = qw(
+    application/x.atom+xml
+    application/xhtml+xml
+    application/xml
+);
+my $content_type = 'text/xml'; # fallback
+foreach my $try_type (@types) {
+    $accept{$try_type} or next;
+    $content_type = $try_type;
+    last;
+}
+
+$r->content_type("$content_type; charset=utf-8");
 
 if (!$class) {
     return $m->comp('index', %ARGS) if $path =~ /index|^\W*$/i;
-    return $m->comp('Error/index', Status => 404);
+    return $m->comp('Elements/Error', Status => 404);
 }
 
 $m->comp(

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 11:58:17 2004
@@ -1,61 +1,20 @@
 %# Put service links to all actions and objects here
 <?xml version="1.0" encoding="utf-8"?>
 <?xml-stylesheet type="text/css" href="<% $BaseURI %>/NoAuth/index.css"?>
-<feed version="0.3"
-  xmlns="http://purl.org/atom/ns#"
-  xmlns:html="http://www.w3.org/1999/xhtml"
->
+<feed version="0.3" xmlns="http://purl.org/atom/ns#">
   <title><&|/l&>Homepage</&></title>
   <author>
     <name><% $RT::Organization %></name>
     <url><% $RT::WebURL %></url>
   </author>
   <& $Link, Type => 'text/html', URI => $RT::WebURL, Title => loc("Homepage") &>
-% foreach my $type (sort @types) {
+% 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) &>
 % }
   <modified><% $Now->W3CDTF %></modified>
   <generator url="http://www.bestpractical.com/rt/" version="<% $RT::VERSION %>">RT</generator>
 </feed>
-<%INIT>
-my %collection_to_obj;
-my %record_to_collection;
-foreach my $key (keys %INC) {
-    $key =~ m{^(RTx?(?:/.+)?/([^_/]+)).pm$}i or next;
-    my ($class, $type) = ($1, $2);
-    $class =~ s{/}{::}g;
-    $class->can('NewItem') or next;
-    my $obj = eval {$class->new($session{CurrentUser})->NewItem} or next;
-    $collection_to_obj{$type} = $obj;
-    $record_to_collection{$1} = $type if ref($obj) =~ /(\w+)$/;
-}
-
-my @collection = sort keys %collection_to_obj;
-my @record = (
-    map {($_, $_."Id")} (qw(Member PrincipalType Object),
-    sort keys %record_to_collection)
-);
-
-my %gone;
-foreach my $type (@collection) {
-    my $obj = $collection_to_obj{$type} or next;
-
-    # First, eliminate collections that can be inferred from other objects
-    foreach my $method (@collection) {
-	$gone{$method}++ if $obj->can($method) or $obj->can("_$method");
-    }
-
-    # Next, eliminate normalization records with multiple parent fields 
-    my $score = 0;
-    foreach my $property (@record) {
-	$score++ if $obj->_Accessible($property, 'read');
-    }
-    $gone{$type}++ if $score > 1;
-}
-
-my @types = sort grep !$gone{$_}, keys %collection_to_obj;
-</%INIT>
 <%ARGS>
 $Path
 $BaseURI


More information about the Rt-commit mailing list