File Coverage

blib/lib/Dancer/Serializer.pm
Criterion Covered Total %
statement 60 60 100.0
branch 16 20 80.0
condition 13 17 76.4
subroutine 11 11 100.0
pod 0 4 0.0
total 100 112 89.2


line stmt bran cond sub pod time code
1             package Dancer::Serializer;
2             our $AUTHORITY = 'cpan:SUKRIA';
3             #ABSTRACT: serializer wrapper for Dancer
4             $Dancer::Serializer::VERSION = '1.3514_04'; # TRIAL
5             $Dancer::Serializer::VERSION = '1.351404';
6             # Factory for serializer engines
7              
8 169     169   1430 use strict;
  169         311  
  169         4265  
9 169     169   743 use warnings;
  169         304  
  169         3821  
10 169     169   792 use Dancer::ModuleLoader;
  169         338  
  169         3799  
11 169     169   794 use Dancer::Engine;
  169         350  
  169         3471  
12 169     169   871 use Dancer::Factory::Hook;
  169         366  
  169         3574  
13 169     169   1987 use Dancer::Error;
  169         323  
  169         4378  
14 169     169   893 use Dancer::SharedData;
  169         304  
  169         84580  
15              
16             Dancer::Factory::Hook->instance->install_hooks(qw/before_deserializer after_deserializer/);
17              
18             my $_engine;
19              
20             sub engine {
21 150 100   150 0 828 $_engine
22             and return $_engine;
23             # don't create a new serializer unless it's defined in the config
24             # (else it's created using json, and that's *not* what we want)
25 7         29 my $serializer_name = Dancer::App->current->setting('serializer');
26 7 50       17 $serializer_name
27             and return Dancer::Serializer->init($serializer_name);
28 7         55 return;
29             }
30              
31             sub init {
32 23     23 0 1033 my ($class, $name, $config) = @_;
33 23   100     72 $name ||= 'JSON';
34 23         145 $_engine = Dancer::Engine->build('serializer' => $name, $config);
35 22         126 return $_engine;
36             }
37              
38             # takes a response object and checks whether or not it should be
39             # serialized.
40             # returns an error object if the serializer fails
41             sub process_response {
42 45     45 0 103 my ($class, $response) = @_;
43              
44 45         106 my $content = $response->{content};
45              
46 45 100 66     246 if (ref($content) && (ref($content) ne 'GLOB')) {
47 30         51 local $@;
48 30         51 eval { $content = engine->serialize($content) };
  30         65  
49              
50             # the serializer failed, replace the response with an error object
51 30 100       638 if ($@) {
52             my $error = Dancer::Error->new(
53             code => 500,
54             message => "Serializer ("
55             . ref($_engine) . ") "
56             . "failed at serializing "
57 7         80 . $response->{content} . ":\n$@",
58             );
59 7         31 $response = $error->render;
60             }
61              
62             # the serializer succeeded, alter the response object accordingly
63             else {
64 23         66 $response->header('Content-Type' => engine->content_type);
65 23         959 $response->{content} = $content;
66             }
67             }
68              
69 45         198 return $response;
70             }
71              
72             # deserialize input params in the request body, if matching the Serializer's
73             # content-type.
74             sub process_request {
75 34     34 0 81 my ($class, $request) = @_;
76              
77 34         118 Dancer::Factory::Hook->execute_hooks('before_deserializer');
78              
79 34 50       758 return $request unless engine;
80              
81             # Content-Type may contain additional parameters
82             # (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7)
83             # which should be safe to ignore at this level.
84             # So accept either e.g. text/xml or text/xml; charset=utf-8
85 34         99 my $content_type = $request->content_type;
86 34         108 $content_type =~ s/ \s* ; .+ $ //x;
87 34 100       103 return $request unless engine->support_content_type($content_type);
88              
89 12 50 100     50 return $request
      66        
      66        
90             unless $request->is_put
91             or $request->is_post
92             or $request->is_patch
93             or $request->is_delete;
94              
95 11         44 my $old_params = $request->params('body');
96              
97             # try to deserialize
98 11         17 my $new_params;
99 11         22 eval {
100 11         30 $new_params = engine->deserialize($request->body)
101             };
102 11 100       314 if ($@) {
103 1         3 Dancer::Logger::core "Unable to deserialize request body with "
104             . engine()
105             . " : \n$@";
106 1         3 return $request;
107             }
108              
109 10 100 66     56 if(!ref $new_params or ref $new_params ne 'HASH'){
110 2         6 return $request;
111             }
112              
113 8 50       48 (keys %$old_params)
114             ? $request->_set_body_params({%$old_params, %$new_params})
115             : $request->_set_body_params($new_params);
116              
117 8         43 Dancer::Factory::Hook->execute_hooks('after_deserializer');
118              
119 8         673 return $request;
120             }
121              
122              
123             1;
124              
125             __END__