File Coverage

blib/lib/HTTP/Engine/Compat.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package HTTP::Engine::Compat;
2 7     7   21012 use Moose;
  0            
  0            
3             our $VERSION = '0.03';
4              
5             #extends 'HTTP::Engine';
6             use HTTP::Engine;
7             use HTTP::Engine::Request;
8             use HTTP::Engine::ResponseFinalizer;
9             use HTTP::Engine::Compat::Context;
10             use HTTP::Engine::Role::Interface;
11              
12             our $rh;
13             my @wraps;
14              
15             sub import {
16             my ( $class, %args ) = @_;
17              
18             $class->_modify(
19             'HTTP::Engine::Request',
20             sub {
21             my $meta = shift;
22             $meta->add_attribute(
23             context => {
24             is => 'rw',
25             isa => 'HTTP::Engine::Compat::Context',
26             weak_ref => 1,
27             }
28             );
29             }
30             );
31              
32             $class->_modify(
33             'HTTP::Engine::Response',
34             sub {
35             my $meta = shift;
36             $meta->add_attribute(
37             location => {
38             is => 'rw',
39             isa => 'Str',
40             }
41             );
42             $meta->add_method(
43             redirect => sub {
44             my $self = shift;
45              
46             if (@_) {
47             $self->location(shift);
48             $self->status( shift || 302 );
49             }
50              
51             $self->location;
52             }
53             );
54             }
55             );
56              
57             $class->_modify(
58             'HTTP::Engine',
59             sub {
60             my $meta = shift;
61             $meta->add_around_method_modifier(
62             'new' => sub {
63             my ($next, @args) = @_;
64             my $instance = $next->(@args);
65              
66             $class->_setup_interface($instance->interface->meta);
67             $instance;
68             },
69             );
70             },
71             );
72              
73             do {
74             my $meta =
75             Class::MOP::Class->initialize('HTTP::Engine::ResponseFinalizer')
76             or die "cannot get meta";
77             $meta->add_around_method_modifier(
78             finalize => sub {
79             my $code = shift;
80             my ( $self, $req, $res ) = @_;
81             if ( my $location = $res->location ) {
82             $res->header( Location => $req->absolute_url($location) );
83             $res->body( $res->status . ': Redirect' ) unless $res->body;
84             }
85             $code->(@_);
86             },
87             );
88             };
89              
90             return unless $args{middlewares} && ref $args{middlewares} eq 'ARRAY';
91             $class->load_middlewares( @{ $args{middlewares} } );
92             }
93              
94             my %initialized;
95             sub _setup_interface {
96             my ($class, $inter) = @_;
97              
98             return if $initialized{$inter->name}++;
99              
100             $inter->make_mutable;
101              
102             $inter->add_method(
103             'call_handler' => sub {
104             my $req = shift;
105             $rh->( $req );
106             }
107             );
108             $class->_wrap( $inter, \&_extract_context );
109             $class->_wrap( $inter, $_ ) for @wraps;
110              
111             $inter->make_mutable;
112             $inter->add_method(
113             'handle_request' => sub {
114             my ( $self, %args ) = @_;
115              
116             my $c = HTTP::Engine::Compat::Context->new(
117             req => HTTP::Engine::Request->new(
118             request_builder => $self->request_builder,
119             %args,
120             ),
121             res => HTTP::Engine::Response->new( status => 200 ),
122             );
123              
124             eval {
125             local $rh = $self->request_handler;
126             my $res = $inter->get_method('call_handler')->($c);
127             if (Scalar::Util::blessed($res) && $res->isa('HTTP::Engine::Response')) {
128             $c->res( $res );
129             }
130             };
131             if ( my $e = $@ ) {
132             print STDERR $e;
133             $c->res->status(500);
134             $c->res->body('internal server error');
135             }
136              
137             HTTP::Engine::ResponseFinalizer->finalize( $c->req => $c->res );
138              
139             $self->response_writer->finalize( $c->req => $c->res );
140             return $c->res;
141             },
142             );
143              
144             $inter->make_immutable;
145             }
146              
147             sub load_middlewares {
148             my ($class, @middlewares) = @_;
149             for my $middleware (@middlewares) {
150             $class->load_middleware( $middleware );
151             }
152             }
153              
154             sub load_middleware {
155             my ($class, $middleware) = @_;
156              
157             my $pkg;
158             if (($pkg = $middleware) =~ s/^(\+)//) {
159             Class::MOP::load_class($pkg);
160             } else {
161             $pkg = 'HTTP::Engine::Middleware::' . $middleware;
162             unless (eval { Class::MOP::load_class($pkg) }) {
163             $pkg = 'HTTPEx::Middleware::' . $middleware;
164             Class::MOP::load_class($pkg);
165             }
166             }
167              
168             if ($pkg->meta->has_method('setup')) {
169             $pkg->setup();
170             }
171              
172             if ($pkg->meta->has_method('wrap')) {
173             push @wraps, $pkg->meta->get_method('wrap')->body;
174             }
175             }
176              
177             sub _wrap {
178             my ($class, $interface, $code ) = @_;
179             $interface->make_mutable;
180             $interface->add_around_method_modifier(
181             call_handler => $code,
182             );
183             $interface->make_immutable;
184             }
185              
186             sub _extract_context {
187             my ($code, $arg) = @_;
188              
189             # process argument
190             if (Scalar::Util::blessed($arg) ne 'HTTP::Engine::Compat::Context') {
191             }
192              
193             my $ret = $code->($arg);
194              
195             # process return value
196             my $res;
197             if (Scalar::Util::blessed($ret) && $ret->isa('HTTP::Engine::Response')) {
198             $res = $ret;
199             } else {
200             $res = $arg->res;
201             }
202              
203             return $res;
204             }
205              
206             sub _modify {
207             my ($class, $target, $cb) = @_;
208             my $meta = $target->meta;
209             $meta->make_mutable if $meta->can('make_mutable');
210             $cb->($meta);
211             $meta->make_immutable if $meta->can('make_immutable');
212             }
213              
214             no Moose;
215             __PACKAGE__->meta->make_immutable;
216             1;
217             __END__