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.3521';
5             # Factory for serializer engines
6              
7 168     168   1231 use strict;
  168         421  
  168         4992  
8 168     168   915 use warnings;
  168         398  
  168         4630  
9 168     168   1028 use Dancer::ModuleLoader;
  168         454  
  168         4589  
10 168     168   1023 use Dancer::Engine;
  168         412  
  168         4179  
11 168     168   908 use Dancer::Factory::Hook;
  168         419  
  168         4359  
12 168     168   2469 use Dancer::Error;
  168         435  
  168         5124  
13 168     168   1123 use Dancer::SharedData;
  168         503  
  168         103599  
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 897 $_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         23 my $serializer_name = Dancer::App->current->setting('serializer');
25 7 50       22 $serializer_name
26             and return Dancer::Serializer->init($serializer_name);
27 7         59 return;
28             }
29              
30             sub init {
31 23     23 0 1319 my ($class, $name, $config) = @_;
32 23   100     91 $name ||= 'JSON';
33 23         167 $_engine = Dancer::Engine->build('serializer' => $name, $config);
34 22         120 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 128 my ($class, $response) = @_;
42              
43 45         92 my $content = $response->{content};
44              
45 45 100 66     236 if (ref($content) && (ref($content) ne 'GLOB')) {
46 30         62 local $@;
47 30         49 eval { $content = engine->serialize($content) };
  30         89  
48              
49             # the serializer failed, replace the response with an error object
50 30 100       725 if ($@) {
51             my $error = Dancer::Error->new(
52             code => 500,
53             message => "Serializer ("
54             . ref($_engine) . ") "
55             . "failed at serializing "
56 7         87 . $response->{content} . ":\n$@",
57             );
58 7         42 $response = $error->render;
59             }
60              
61             # the serializer succeeded, alter the response object accordingly
62             else {
63 23         68 $response->header('Content-Type' => engine->content_type);
64 23         1083 $response->{content} = $content;
65             }
66             }
67              
68 45         220 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 98 my ($class, $request) = @_;
75              
76 34         126 Dancer::Factory::Hook->execute_hooks('before_deserializer');
77              
78 34 50       869 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         97 my $content_type = $request->content_type;
85 34         143 $content_type =~ s/ \s* ; .+ $ //x;
86 34 100       75 return $request unless engine->support_content_type($content_type);
87              
88 12 50 100     72 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         53 my $old_params = $request->params('body');
95              
96             # try to deserialize
97 11         18 my $new_params;
98 11         16 eval {
99 11         32 $new_params = engine->deserialize($request->body)
100             };
101 11 100       329 if ($@) {
102 1         3 Dancer::Logger::core "Unable to deserialize request body with "
103             . engine()
104             . " : \n$@";
105 1         3 return $request;
106             }
107              
108 10 100 66     85 if(!ref $new_params or ref $new_params ne 'HASH'){
109 2         6 return $request;
110             }
111              
112 8 50       58 (keys %$old_params)
113             ? $request->_set_body_params({%$old_params, %$new_params})
114             : $request->_set_body_params($new_params);
115              
116 8         48 Dancer::Factory::Hook->execute_hooks('after_deserializer');
117              
118 8         825 return $request;
119             }
120              
121              
122             1;
123              
124             __END__