File Coverage

blib/lib/Mojolicious/Plugin/MoreHelpers.pm
Criterion Covered Total %
statement 3 118 2.5
branch 0 20 0.0
condition 0 43 0.0
subroutine 1 16 6.2
pod 1 1 100.0
total 5 198 2.5


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::MoreHelpers;
2 1     1   616 use Mojo::Base 'Mojolicious::Plugin';
  1         3  
  1         7  
3              
4             our $VERSION = '0.02';
5             $VERSION = eval $VERSION;
6              
7             sub register {
8 0     0 1   my ($self, $app, $conf) = @_;
9              
10             $app->helper(route_params => sub {
11 0     0     my ($c, @names) = @_;
12              
13 0           my $route = $c->match->endpoint;
14              
15 0           my %params;
16              
17 0           while ($route) {
18 0           for my $name (@names) {
19 0 0         next if exists $params{$name};
20 0 0         next unless exists $route->to->{$name};
21              
22 0           $params{$name} = $route->to->{$name};
23             }
24              
25 0           $route = $route->parent;
26             }
27              
28 0           return \%params;
29 0           });
30              
31             $app->helper(validation_json => sub {
32 0     0     my ($c) = @_;
33              
34 0           my $v = $c->validation;
35              
36 0   0       my $json = $c->req->json || { };
37 0 0         $json = { } unless ref $json eq 'HASH';
38              
39 0           for my $key (keys %$json) {
40 0           my $success = 0;
41              
42 0 0         if (not ref $json->{$key}) { $success = 1 }
  0 0          
43              
44             elsif (ref $json->{$key} eq 'ARRAY') {
45             # Success only if there are no any refs in array
46 0 0         $success = 1 unless grep { ref $_ } @{$json->{$key}};
  0            
  0            
47             }
48              
49 0 0         $v->input->{$key} = $json->{$key} if $success;
50             }
51              
52 0           return $v;
53 0           });
54              
55             $app->helper(headers_more => sub {
56 0     0     my ($c, %headers) = @_;
57              
58 0           my $h = $c->res->headers;
59              
60 0           $h->header($_ => $headers{$_}) for keys %headers;
61              
62 0           return $c;
63 0           });
64              
65             $app->helper('reply_json.success' => sub {
66 0     0     my ($c, $json, %onward) = @_;
67              
68 0           my $h = $c->res->headers;
69              
70 0 0         my $default_status = $c->req->method eq 'POST' ? 201 : 200;
71 0   0       my $status = $onward{status} || $default_status;
72              
73 0   0       $c->render(json => $json || { }, status => $status);
74 0           });
75              
76             $app->helper('reply_json.bad_request' => sub {
77 0     0     my ($c, %onward) = @_;
78              
79 0           my $h = $c->res->headers;
80              
81 0   0       my $status = $onward{status} || 400;
82 0   0       my $message = $onward{message} || "error.validation_failed";
83              
84 0           $h->header('X-Message' => $message);
85 0           $c->render(json => { }, status => $status);
86 0           });
87              
88             $app->helper('reply_json.unauthorized' => sub {
89 0     0     my ($c, %onward) = @_;
90              
91 0           my $h = $c->res->headers;
92              
93 0   0       my $status = $onward{status} || 401;
94 0   0       my $message = $onward{message} || "error.authorization_failed";
95              
96 0           $h->header('X-Message' => $message);
97 0           $c->render(json => { }, status => $status);
98 0           });
99              
100             $app->helper('reply_json.forbidden' => sub {
101 0     0     my ($c, %onward) = @_;
102              
103 0           my $h = $c->res->headers;
104              
105 0   0       my $status = $onward{status} || 403;
106 0   0       my $message = $onward{message} || "error.access_denied";
107              
108 0           $h->header('X-Message' => $message);
109 0           $c->render(json => { }, status => $status);
110 0           });
111              
112             $app->helper('reply_json.not_found' => sub {
113 0     0     my ($c, %onward) = @_;
114              
115 0           my $h = $c->res->headers;
116              
117 0   0       my $status = $onward{status} || 404;
118 0   0       my $message = $onward{message} || "error.resource_not_found";
119              
120 0           $h->header('X-Message' => $message);
121 0           $c->render(json => { }, status => $status);
122 0           });
123              
124             $app->helper('reply_json.not_acceptable' => sub {
125 0     0     my ($c, %onward) = @_;
126              
127 0           my $h = $c->res->headers;
128              
129 0   0       my $status = $onward{status} || 406;
130 0   0       my $message = $onward{message} || "error.not_acceptable";
131              
132 0           $h->header('X-Message' => $message);
133 0           $c->render(json => { }, status => $status);
134 0           });
135              
136             $app->helper('reply_json.unprocessable' => sub {
137 0     0     my ($c, %onward) = @_;
138              
139 0           my $h = $c->res->headers;
140              
141 0   0       my $status = $onward{status} || 422;
142 0   0       my $message = $onward{message} || "error.unprocessable_entity";
143              
144 0           $h->header('X-Message' => $message);
145 0           $c->render(json => { }, status => $status);
146 0           });
147              
148             $app->helper('reply_json.locked' => sub {
149 0     0     my ($c, %onward) = @_;
150              
151 0           my $h = $c->res->headers;
152              
153 0   0       my $status = $onward{status} || 423;
154 0   0       my $message = $onward{message} || "error.temporary_locked";
155              
156 0           $h->header('X-Message' => $message);
157 0           $c->render(json => { }, status => $status);
158 0           });
159              
160             $app->helper('reply_json.rate_limit' => sub {
161 0     0     my ($c, %onward) = @_;
162              
163 0           my $h = $c->res->headers;
164              
165 0   0       my $status = $onward{status} || 429;
166 0   0       my $message = $onward{message} || "error.too_many_requests";
167              
168 0           $h->header('X-Message' => $message);
169 0           $c->render(json => { }, status => $status);
170 0           });
171              
172             $app->helper('reply_json.unavailable' => sub {
173 0     0     my ($c, %onward) = @_;
174              
175 0           my $h = $c->res->headers;
176              
177 0   0       my $status = $onward{status} || 503;
178 0   0       my $message = $onward{message} || "error.service_unavailable";
179              
180 0           $h->header('X-Message' => $message);
181 0           $c->render(json => { }, status => $status);
182 0           });
183              
184             $app->helper('reply_json.catch' => sub {
185 0     0     my ($c, $message, $status, %onward) = @_;
186              
187             # Compile error if there is no status defined
188 0 0         return $c->reply->exception($message) unless $status;
189              
190             my %dispatch = (
191 0           bad_request => sub { $c->reply_json->bad_request(@_) },
192 0           unauthorized => sub { $c->reply_json->unauthorized(@_) },
193 0           forbidden => sub { $c->reply_json->forbidden(@_) },
194 0           not_found => sub { $c->reply_json->not_found(@_) },
195 0           unprocessable => sub { $c->reply_json->unprocessable(@_) },
196 0           locked => sub { $c->reply_json->locked(@_) },
197 0           rate_limit => sub { $c->reply_json->rate_limit(@_) },
198 0           unavailable => sub { $c->reply_json->unavailable(@_) },
199 0           );
200              
201 0           my $reply_json = $dispatch{$status};
202              
203 0 0         die "Wrong reply_json catch status '$status'\n"
204             unless defined $reply_json;
205              
206 0           $reply_json->(%onward, message => $message);
207 0           });
208             }
209              
210             1;
211              
212             =encoding utf8
213              
214             =head1 NAME
215              
216             Mojolicious::Plugin::MoreHelpers - More helpers lacking in Mojolicious
217              
218             =head1 SYNOPSIS
219              
220             # Mojolicious
221             $app->plugin('MoreHelpers');
222              
223             # Mojolicious::Lite
224             plugin 'MoreHelpers';
225              
226             =head1 DESCRIPTION
227              
228             L is a mingle of helpers lacking in
229             L Web framework for REST-like APIs.
230              
231             =head1 HELPERS
232              
233             L implements the following helpers.
234              
235             =head2 route_params
236              
237             my $params = $c->route_params(@names);
238              
239             Recursive collect current route params and his parents.
240              
241             =head2 validation_json
242              
243             my $v = $c->validation_json;
244              
245             Merge flat request JSON object with validation.
246              
247             =head2 headers_more
248              
249             my $h = $c->headers_more(%headers);
250              
251             Set multiple reponse headers in one time.
252              
253             =head2 reply_json->success
254              
255             $c->reply_json->success($data, %onward);
256              
257             Render the success JSON object with status code, depend on POST or GET request.
258              
259             =head2 reply_json->bad_request
260              
261             $c->reply_json->bad_request(%onward);
262              
263             Render empty JSON object with 400 Bad Request HTTP status.
264              
265             =head2 reply_json->unquthorized
266              
267             $c->reply_json->unauthorized(%onward);
268              
269             Render empty JSON object with 401 HTTP status.
270              
271             =head2 reply_json->forbidden
272              
273             $c->reply_json->forbidden(%onward);
274              
275             Render empty JSON object with 403 Forbidden HTTP status.
276              
277             =head2 reply_json->not_found
278              
279             $c->reply_json->not_found(%onward);
280              
281             Render empty JSON object with 404 Not Found HTTP status.
282              
283             =head2 reply_json->not_acceptable
284              
285             $c->reply-_json>not_acceptable(%onward);
286              
287             Render empty JSON object with 406 HTTP status.
288              
289             =head2 reply_json->unprocessable
290              
291             $c->reply_json->unprocessable(%onward);
292              
293             Render empty JSON object with 422 HTTP status.
294              
295             =head2 reply_json->locked
296              
297             $c->reply_json->locked(%onward);
298              
299             Render empty JSON object with 423 HTTP status.
300              
301             =head2 reply_json->rate_limit
302              
303             $c->reply_json->rate_limit(%onward);
304              
305             Render empty JSON object with 429 HTTP status.
306              
307             =head2 reply_json->unavailable
308              
309             $c->reply_json->unavailable(%onward);
310              
311             Render empty JSON object with 503 HTTP status.
312              
313             =head2 reply_json->catch
314              
315             $c->reply_json->catch($message, $status, %onward);
316              
317             Dispatch with status and render properly error code.
318              
319             =head1 METHODS
320              
321             L inherits all methods from L
322             and implements the following new ones.
323              
324             =head2 register
325              
326             $plugin->register(Mojolicious->new);
327              
328             Register helpers in L application.
329              
330             =head1 SEE ALSO
331              
332             L.
333              
334             =head1 SUPPORT
335              
336             =head2 Bugs / Feature Requests
337              
338             Bugs should always be submitted via the GitHub bug tracker.
339              
340             L
341              
342             =head2 Source Code
343              
344             Feel free to fork the repository and submit pull requests.
345              
346             L
347              
348             =head1 AUTHOR
349              
350             Dmitry Krutikov Emonstar@cpan.orgE
351              
352             =head1 COPYRIGHT AND LICENSE
353              
354             Copyright 2020 Dmitry Krutikov.
355              
356             This library is free software; you can redistribute it and/or modify it
357             under the same terms as Perl itself.
358              
359             =cut
360