File Coverage

blib/lib/Chouette/Context.pm
Criterion Covered Total %
statement 44 70 62.8
branch 3 20 15.0
condition 3 15 20.0
subroutine 13 20 65.0
pod 0 11 0.0
total 63 136 46.3


line stmt bran cond sub pod time code
1             package Chouette::Context;
2              
3 1     1   3 use common::sense;
  1         1  
  1         6  
4              
5 1     1   437 use Plack::Request::WithEncoding;
  1         36966  
  1         23  
6 1     1   395 use Plack::Response;
  1         1335  
  1         28  
7 1     1   413 use Log::Defer;
  1         2194  
  1         23  
8 1     1   4 use JSON::XS;
  1         1  
  1         41  
9 1     1   3 use Data::Dumper;
  1         1  
  1         858  
10              
11              
12             sub new {
13 1     1 0 3 my ($class, %args) = @_;
14              
15 1         1 my $self = \%args;
16 1         2 bless $self, $class;
17              
18 1         16 $self->{req} = Plack::Request::WithEncoding->new($self->{env});
19 1         13 $self->{req}->env->{'plack.request.withencoding.encoding'} = 'utf-8';
20              
21              
22 1         5 my $raw_logger = $self->{chouette}->{raw_logger};
23              
24             $self->{log_defer_obj} = Log::Defer->new({ cb => sub {
25 1     1   21 my $msg = shift;
26              
27 1         1 my $encoded_msg = eval { encode_json($msg) };
  1         13  
28              
29 1 50       5 if ($@) {
30 0         0 $encoded_msg = eval { encode_json(_json_clean($msg)) };
  0         0  
31              
32 0 0       0 if ($@) {
33 0         0 $encoded_msg = "Failed to JSON clean: " . Dumper($msg);
34             }
35             }
36              
37 1         5 $raw_logger->log("$encoded_msg\n");
38 1         8 }});
39              
40 1         40 return $self;
41             }
42              
43              
44 0     0 0 0 sub config { shift->{chouette}->{config} }
45 2     2 0 16 sub logger { shift->{log_defer_obj} }
46 1     1 0 2 sub req { shift->{req} }
47 0     0 0 0 sub res { die "Plack response object not yet supported" }
48 0   0 0 0 0 sub route_params { shift->{route_params} // {} }
49              
50              
51             sub respond_raw {
52 1     1 0 2 my ($self, $http_code, $mime_type, $body) = @_;
53              
54 1 50       3 if (defined $self->{responder}) {
55 1         2 $self->logger->info("HTTP response: $http_code (" . length($body) . " bytes of $mime_type)");
56 1         25 $self->{responder}->([$http_code, ["Content-Type" => $mime_type], [$body]]);
57 1         11 undef $self->{responder};
58             } else {
59 0         0 $self->logger->info("Not replying with $http_code because something else already replied.");
60             }
61              
62 1         6 return $self->{chouette}->{_done_gensym};
63             }
64              
65              
66             sub DESTROY {
67 1     1   33 my $self = shift;
68              
69 1 50       25 if (defined $self->{responder}) {
70 0         0 $self->logger->error("no response was sent, sending 500");
71 0         0 $self->respond({ error => 'internal server error' }, 500);
72             }
73             }
74              
75              
76             sub respond {
77 1     1 0 7 my ($self, $body, $http_code) = @_;
78              
79 1 0 33     3 if (defined $http_code && $http_code != 200 && ref($body) eq 'HASH' && exists $body->{error}) {
      33        
      0        
80 0         0 $self->logger->warn("sending JSON error: $body->{error}");
81             }
82              
83 1   50     17 return $self->respond_raw($http_code // 200, 'application/json', encode_json($body));
84             }
85              
86              
87              
88             sub done {
89 0     0 0   die shift->{chouette}->{_done_gensym};
90             }
91              
92              
93             sub generate_token {
94 0     0 0   shift->{chouette}->generate_token();
95             }
96              
97              
98              
99             sub task {
100 0     0 0   my ($self, $task_name, %checkout_opts) = @_;
101              
102 0 0         return $self->{task_checkouts}->{$task_name} if $self->{task_checkouts}->{$task_name};
103              
104 0   0       my $client = $self->{chouette}->{task_clients}->{$task_name} // die "no such task: '$task_name'";
105 0           my $checkout = $client->checkout(log_defer_object => $self->logger, %checkout_opts);
106              
107 0 0         $self->{task_checkouts}->{$task_name} = $checkout if $self->{chouette}->{task_checkout_caching}->{$task_name};
108              
109 0           return $checkout;
110             }
111              
112              
113              
114              
115              
116             ########
117              
118              
119             sub _json_clean {
120 0     0     my $x = shift;
121              
122 0 0         if (ref $x) {
123 0 0         if (ref $x eq 'ARRAY') {
    0          
124 0           $x->[$_] = _json_clean($x->[$_]) for 0 .. @$x-1;
125             } elsif (ref $x eq 'HASH') {
126 0           $x->{$_} = _json_clean($x->{$_}) for keys %$x;
127             } else {
128 0           $x = "Unable to JSON encode: " . Dumper($x);
129             }
130             }
131              
132 0           return $x;
133             }
134              
135              
136              
137             1;