r1682@mbp: claco | 2008-06-16 19:54:33 -0400
claco [Mon, 16 Jun 2008 23:54:50 +0000 (23:54 +0000)]
 Added support for application/json and wanr when using text/x-json

Changelog
lib/Catalyst/Action/SerializeBase.pm
lib/Catalyst/Controller/REST.pm
lib/Catalyst/Request/REST.pm
t/catalyst-request-rest.t
t/json.t
t/lib/Test/Serialize/Controller/REST.pm

index 2238a63..84e0c24 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,5 @@
+  Support official application/json and carp about text/x-json
+
 Thu Jan  3 17:23:58 PST 2008 (adam) - Release 0.60
   Updated my contact information.
   Prepped for release.
index dde60ec..7a2980f 100644 (file)
@@ -38,6 +38,12 @@ sub _load_content_plugins {
 
     my $content_type = $c->request->preferred_content_type || '';
 
+    # carp about old text/x-json
+    if ($content_type eq 'text/x-json') {
+        $c->log->info('Using deprecated text/x-json content-type.');
+        $c->log->info('Use application/json instead!');
+    }
+
     # Finally, we load the class.  If you have a default serializer,
     # and we still don't have a content-type that exists in the map,
     # we'll use it.
index 5d267b3..c8cb7a3 100644 (file)
@@ -218,6 +218,7 @@ __PACKAGE__->config(
             'text/html'          => 'YAML::HTML',
             'text/xml'           => 'XML::Simple',
             'text/x-yaml'        => 'YAML',
+            'application/json'   => 'JSON',
             'text/x-json'        => 'JSON',
             'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ],
             'text/x-data-denter' => [ 'Data::Serializer', 'Data::Denter' ],
@@ -415,6 +416,7 @@ This class provides a default configuration for Serialization.  It is currently:
             'text/html'          => 'YAML::HTML',
             'text/xml'           => 'XML::Simple',
             'text/x-yaml'        => 'YAML',
+            'application/json'   => 'JSON',
             'text/x-json'        => 'JSON',
             'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ],
             'text/x-data-denter' => [ 'Data::Serializer', 'Data::Denter' ],
index 4f3dab0..40a9a39 100644 (file)
@@ -20,7 +20,7 @@ Catalyst::Request::REST - A REST-y subclass of Catalyst::Request
 
 =head1 SYNOPSIS
 
-     if ( $c->request->accepts('text/x-json') ) {
+     if ( $c->request->accepts('application/json') ) {
          ...
      }
 
index 3fd4c09..4493897 100644 (file)
@@ -1,6 +1,6 @@
 use strict;
 use warnings;
-use Test::More tests => 21;
+use Test::More tests => 24;
 use FindBin;
 use lib ( "$FindBin::Bin/../lib" );
 
@@ -112,6 +112,31 @@ use HTTP::Headers;
     $request->headers( HTTP::Headers->new );
     $request->parameters( {} );
     $request->method('GET');
+    $request->content_type('application/json');
+    $request->headers->header(
+        'Accept' =>
+        # From Firefox 2.0 when it requests an html page
+        'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
+    );
+
+    is_deeply( $request->accepted_content_types,
+               [ qw( application/json
+                     text/xml application/xml application/xhtml+xml
+                     image/png
+                     text/html
+                     text/plain
+                     */*
+                   ) ],
+               'accept header is parsed properly, and content-type header has precedence over accept' );
+    ok( ! $request->accept_only, 'accept_only is false' );
+}
+
+{
+    my $request = Catalyst::Request::REST->new;
+    $request->{_context} = 'MockContext';
+    $request->headers( HTTP::Headers->new );
+    $request->parameters( {} );
+    $request->method('GET');
     $request->content_type('text/x-json');
     $request->headers->header(
         'Accept' => 'text/plain,text/x-json',
@@ -124,6 +149,23 @@ use HTTP::Headers;
                'each type appears only once' );
 }
 
+{
+    my $request = Catalyst::Request::REST->new;
+    $request->{_context} = 'MockContext';
+    $request->headers( HTTP::Headers->new );
+    $request->parameters( {} );
+    $request->method('GET');
+    $request->content_type('application/json');
+    $request->headers->header(
+        'Accept' => 'text/plain,application/json',
+    );
+
+    is_deeply( $request->accepted_content_types,
+               [ qw( application/json
+                     text/plain
+                   ) ],
+               'each type appears only once' );
+}
 
 package MockContext;
 
index a5380de..8b05bc4 100644 (file)
--- a/t/json.t
+++ b/t/json.t
@@ -1,6 +1,6 @@
 use strict;
 use warnings;
-use Test::More tests => 5; 
+use Test::More tests => 9; 
 use FindBin;
 
 use lib ("$FindBin::Bin/lib", "$FindBin::Bin/../lib");
@@ -8,25 +8,27 @@ use Test::Rest;
 
 use_ok 'Catalyst::Test', 'Test::Serialize';
 
-my $t = Test::Rest->new('content_type' => 'text/x-json');
-
-my $has_serializer = eval "require JSON::Syck";
 SKIP: {
-    skip "JSON::Syck not available", 4, unless $has_serializer;
+    my $has_serializer = eval "require JSON::Syck";
+
+    skip "JSON::Syck not available", 8, unless $has_serializer;
 
-    my $monkey_template = {
-        monkey => 'likes chicken!',
-    };
-    my $mres = request($t->get(url => '/monkey_get'));
-    ok( $mres->is_success, 'GET the monkey succeeded' );
-    is_deeply(JSON::Syck::Load($mres->content), $monkey_template, "GET returned the right data");
+    for ('text/x-json', 'application/json') {
+        my $t = Test::Rest->new('content_type' => $_);
+        my $monkey_template = {
+            monkey => 'likes chicken!',
+        };
+        my $mres = request($t->get(url => '/monkey_get'));
+        ok( $mres->is_success, 'GET the monkey succeeded' );
+        is_deeply(JSON::Syck::Load($mres->content), $monkey_template, "GET returned the right data");
 
-    my $post_data = {
-        'sushi' => 'is good for monkey',
-    };
-    my $mres_post = request($t->post(url => '/monkey_put', data => JSON::Syck::Dump($post_data)));
-    ok( $mres_post->is_success, "POST to the monkey succeeded");
-    is_deeply($mres_post->content, "is good for monkey", "POST data matches");
+        my $post_data = {
+            'sushi' => 'is good for monkey',
+        };
+        my $mres_post = request($t->post(url => '/monkey_put', data => JSON::Syck::Dump($post_data)));
+        ok( $mres_post->is_success, "POST to the monkey succeeded");
+        is_deeply($mres_post->content, "is good for monkey", "POST data matches");
+    }
 };
 
 1;
index abeb01f..0499f1d 100644 (file)
@@ -12,6 +12,7 @@ __PACKAGE__->config(
         'text/html'          => 'YAML::HTML',
         'text/xml'           => 'XML::Simple',
         'text/x-yaml'        => 'YAML',
+        'application/json'   => 'JSON',
         'text/x-json'        => 'JSON',
         'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ],
         'text/x-data-denter' => [ 'Data::Serializer', 'Data::Denter' ],