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.3520';
5             # Factory for serializer engines
6              
7 168     168   1216 use strict;
  168         427  
  168         5094  
8 168     168   927 use warnings;
  168         465  
  168         4717  
9 168     168   1052 use Dancer::ModuleLoader;
  168         540  
  168         4886  
10 168     168   992 use Dancer::Engine;
  168         457  
  168         4338  
11 168     168   922 use Dancer::Factory::Hook;
  168         425  
  168         4528  
12 168     168   2574 use Dancer::Error;
  168         521  
  168         5464  
13 168     168   1128 use Dancer::SharedData;
  168         551  
  168         107237  
14              
15             Dancer::Factory::Hook->instance->install_hooks(qw/before_deserializer after_deserializer/);
16              
17             my $_engine;
18              
19             sub engine {
20 150 100   150 0 922 $_engine
21             and return $_engine;
22             # don't create a new serializer unless it's defined in the config
23             # (else it's created using json, and that's *not* what we want)
24 7         21 my $serializer_name = Dancer::App->current->setting('serializer');
25 7 50       23 $serializer_name
26             and return Dancer::Serializer->init($serializer_name);
27 7         55 return;
28             }
29              
30             sub init {
31 23     23 0 1343 my ($class, $name, $config) = @_;
32 23   100     90 $name ||= 'JSON';
33 23         175 $_engine = Dancer::Engine->build('serializer' => $name, $config);
34 22         119 return $_engine;
35             }
36              
37             # takes a response object and checks whether or not it should be
38             # serialized.
39             # returns an error object if the serializer fails
40             sub process_response {
41 45     45 0 163 my ($class, $response) = @_;
42              
43 45         98 my $content = $response->{content};
44              
45 45 100 66     265 if (ref($content) && (ref($content) ne 'GLOB')) {
46 30         60 local $@;
47 30         55 eval { $content = engine->serialize($content) };
  30         84  
48              
49             # the serializer failed, replace the response with an error object
50 30 100       717 if ($@) {
51             my $error = Dancer::Error->new(
52             code => 500,
53             message => "Serializer ("
54             . ref($_engine) . ") "
55             . "failed at serializing "
56 7         73 . $response->{content} . ":\n$@",
57             );
58 7         27 $response = $error->render;
59             }
60              
61             # the serializer succeeded, alter the response object accordingly
62             else {
63 23         109 $response->header('Content-Type' => engine->content_type);
64 23         1120 $response->{content} = $content;
65             }
66             }
67              
68 45         253 return $response;
69             }
70              
71             # deserialize input params in the request body, if matching the Serializer's
72             # content-type.
73             sub process_request {
74 34     34 0 95 my ($class, $request) = @_;
75              
76 34         191 Dancer::Factory::Hook->execute_hooks('before_deserializer');
77              
78 34 50       955 return $request unless engine;
79              
80             # Content-Type may contain additional parameters
81             # (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7)
82             # which should be safe to ignore at this level.
83             # So accept either e.g. text/xml or text/xml; charset=utf-8
84 34         104 my $content_type = $request->content_type;
85 34         118 $content_type =~ s/ \s* ; .+ $ //x;
86 34 100       64 return $request unless engine->support_content_type($content_type);
87              
88 12 50 100     56 return $request
      66        
      66        
89             unless $request->is_put
90             or $request->is_post
91             or $request->is_patch
92             or $request->is_delete;
93              
94 11         47 my $old_params = $request->params('body');
95              
96             # try to deserialize
97 11         19 my $new_params;
98 11         24 eval {
99 11         31 $new_params = engine->deserialize($request->body)
100             };
101 11 100       337 if ($@) {
102 1         4 Dancer::Logger::core "Unable to deserialize request body with "
103             . engine()
104             . " : \n$@";
105 1         4 return $request;
106             }
107              
108 10 100 66     85 if(!ref $new_params or ref $new_params ne 'HASH'){
109 2         8 return $request;
110             }
111              
112 8 50       73 (keys %$old_params)
113             ? $request->_set_body_params({%$old_params, %$new_params})
114             : $request->_set_body_params($new_params);
115              
116 8         42 Dancer::Factory::Hook->execute_hooks('after_deserializer');
117              
118 8         801 return $request;
119             }
120              
121              
122             1;
123              
124             __END__