/usr/share/perl5/Plack/Middleware/Recursive.pm is in libplack-perl 0.9985-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | package Plack::Middleware::Recursive;
use strict;
use parent qw(Plack::Middleware);
use Try::Tiny;
use Scalar::Util qw(blessed);
open my $null_io, "<", \"";
sub call {
my($self, $env) = @_;
$env->{'plack.recursive.include'} = $self->recurse_callback($env, 1);
my $res = try {
$self->app->($env);
} catch {
if (blessed $_ && $_->isa('Plack::Recursive::ForwardRequest')) {
return $self->recurse_callback($env)->($_->path);
} else {
die $_; # rethrow
}
};
return $res if ref $res eq 'ARRAY';
return sub {
my $respond = shift;
my $writer;
try {
$res->(sub { return $writer = $respond->(@_) });
} catch {
if (!$writer && blessed $_ && $_->isa('Plack::Recursive::ForwardRequest')) {
$res = $self->recurse_callback($env)->($_->path);
return ref $res eq 'CODE' ? $res->($respond) : $respond->($res);
} else {
die $_;
}
};
};
}
sub recurse_callback {
my($self, $env, $include) = @_;
my $old_path_info = $env->{PATH_INFO};
return sub {
my $new_path_info = shift;
my($path, $query) = split /\?/, $new_path_info, 2;
Scalar::Util::weaken($env);
$env->{PATH_INFO} = $path;
$env->{QUERY_STRING} = $query;
$env->{REQUEST_METHOD} = 'GET';
$env->{CONTENT_LENGTH} = 0;
$env->{CONTENT_TYPE} = '';
$env->{'psgi.input'} = $null_io;
push @{$env->{'plack.recursive.old_path_info'}}, $old_path_info;
$include ? $self->app->($env) : $self->call($env);
};
}
package Plack::Recursive::ForwardRequest;
use overload q("") => \&as_string, fallback => 1;
sub new {
my($class, $path) = @_;
bless { path => $path }, $class;
}
sub path { $_[0]->{path} }
sub throw {
my($class, @args) = @_;
die $class->new(@args);
}
sub as_string {
my $self = shift;
return "Forwarding to $self->{path}: Your application should be wrapped with Plack::Middleware::Recursive.";
}
package Plack::Middleware::Recursive;
1;
__END__
=head1 NAME
Plack::Middleware::Recursive - Allows PSGI apps to include or forward requests recursively
=head1 SYNOPSIS
# with Builder
enable "Recursive";
# in apps
my $res = $env->{'plack.recursive.include'}->("/new_path");
# Or, use exceptions
my $app = sub {
# ...
Plack::Recursive::ForwardRequest->throw("/new_path");
};
=head1 DESCRIPTION
Plack::Middleware::Recursive allows PSGI applications to recursively
include or forward requests to other paths. Applications can make use
of callbacks stored in C<< $env->{'plack.recursive.include'} >> to
I<include> another path to get the response (whether it's an array ref
or a code ref depending on your application), or throw an exception
Plack::Recursive::ForwardRequest anywhere in the code to I<forward>
the current request (i.e. abort the current and redo the request).
=head1 EXCEPTIONS
This middleware passes through unknown exceptions to the outside
middleware stack, so if you use this middleware with other exception
handlers such as L<Plack::Middleware::StackTrace> or
L<Plack::Middleware::HTTPExceptions>, be sure to wrap this so
L<Plack::Middleware::Recursive> gets as inner as possible.
=head1 AUTHORS
Tatsuhiko Miyagawa
Masahiro Honma
=head1 SEE ALSO
L<Plack> L<Plack::Middleware::HTTPExceptions>
The idea, code and interface are stolen from Rack::Recursive and paste.recursive.
=cut
|