/usr/share/perl5/Plack/Middleware/Debug.pm is in libplack-middleware-debug-perl 0.16+dfsg-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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | package Plack::Middleware::Debug;
use 5.008_001;
use strict;
use warnings;
use parent qw(Plack::Middleware);
our $VERSION = '0.16';
use Encode;
use File::ShareDir;
use Plack::App::File;
use Plack::Builder;
use Plack::Util::Accessor qw(panels renderer files);
use Plack::Util;
use Plack::Middleware::Debug::Panel;
use Text::MicroTemplate;
use Try::Tiny;
sub TEMPLATE {
<<'EOTMPL' }
% my $stash = $_[0];
<script type="text/javascript" charset="utf-8">
// When jQuery is sourced, it's going to overwrite whatever might be in the
// '$' variable, so store a reference of it in a temporary variable...
var _$ = window.$;
if (typeof jQuery == 'undefined') {
var jquery_url = '<%= $stash->{BASE_URL} %>/debug_toolbar/jquery.js';
document.write(unescape('%3Cscript src="' + jquery_url + '" type="text/javascript"%3E%3C/script%3E'));
}
</script>
<script type="text/javascript" src="<%= $stash->{BASE_URL} %>/debug_toolbar/toolbar.min.js"></script>
<script type="text/javascript" charset="utf-8">
// Now that jQuery is done loading, put the '$' variable back to what it was...
var $ = _$;
</script>
<style type="text/css">
@import url(<%= $stash->{BASE_URL} %>/debug_toolbar/toolbar.min.css);
</style>
<div id="plDebug">
<div style="display:none;" id="plDebugToolbar">
<ul id="plDebugPanelList">
% if ($stash->{panels}) {
<li><a id="plHideToolBarButton" href="#" title="Hide Toolbar">Hide »</a></li>
% } else {
<li id="plDebugButton">DEBUG</li>
% }
% for my $panel (reverse @{$stash->{panels}}) {
<li>
% if ($panel->content) {
<a href="<%= $panel->url %>" title="<%= $panel->title %>" class="<%= $panel->dom_id %>">
% } else {
<div class="contentless">
% }
<%= $panel->nav_title %>
% if ($panel->nav_subtitle) {
<br><small><%= $panel->nav_subtitle %></small>
% }
% if ($panel->content) {
</a>
% } else {
</div>
% }
</li>
% } # end for
</ul>
</div>
<div style="display:none;" id="plDebugToolbarHandle">
<a title="Show Toolbar" id="plShowToolBarButton" href="#">«</a>
</div>
% for my $panel (reverse @{$stash->{panels}}) {
% if ($panel->content) {
<div id="<%= $panel->dom_id %>" class="panelContent">
<div class="plDebugPanelTitle">
<a href="" class="plDebugClose">Close</a>
<h3><%= $panel->title %></h3>
</div>
<div class="plDebugPanelContent">
<div class="scroll">
% my $content = ref $panel->content eq 'CODE' ? $panel->content->() : $panel->content;
% $content = Encode::encode('latin1', $content, Encode::FB_XMLCREF);
<%= Text::MicroTemplate::encoded_string($content) %>
</div>
</div>
</div>
% }
% } # end for
<div id="plDebugWindow" class="panelContent"></div>
</div>
EOTMPL
sub default_panels {
[qw(Environment Response Timer Memory Session DBITrace)];
}
sub prepare_app {
my $self = shift;
my $root = try { File::ShareDir::dist_dir('Plack-Middleware-Debug') } || 'share';
my $builder = Plack::Builder->new;
for my $spec (@{ $self->panels || $self->default_panels }) {
my ($package, %args);
if (ref $spec eq 'ARRAY') {
# For the backward compatiblity
# [ 'PanelName', key1 => $value1, ... ]
$package = shift @$spec;
$builder->add_middleware("Debug::$package", @$spec);
} else {
# $spec could be a code ref (middleware) or a string
# copy so that we do not change default_panels
my $spec_copy = $spec;
$spec_copy = "Debug::$spec_copy" unless ref $spec_copy;
$builder->add_middleware($spec_copy);
}
}
$self->app( $builder->to_app($self->app) );
$self->renderer(
Text::MicroTemplate->new(
template => $self->TEMPLATE,
tag_start => '<%',
tag_end => '%>',
line_start => '%',
)->build
);
$self->files(Plack::App::File->new(root => $root));
}
sub call {
my ($self, $env) = @_;
if ($env->{PATH_INFO} =~ m!^/debug_toolbar!) {
return $self->files->call($env);
}
$env->{'plack.debug.panels'} = [];
my $res = $self->app->($env);
$self->response_cb($res, sub {
my $res = shift;
my $headers = Plack::Util::headers($res->[1]);
my $panels = delete $env->{'plack.debug.panels'};
if ( ! Plack::Util::status_with_no_entity_body($res->[0])
&& ($headers->get('Content-Type') || '') =~ m!^(?:text/html|application/xhtml\+xml)!) {
my $vars = {
panels => [ grep !$_->disabled, @$panels ],
BASE_URL => $env->{SCRIPT_NAME},
};
my $content = $self->renderer->($vars);
return sub {
my $chunk = shift;
return unless defined $chunk;
$chunk =~ s!(?=</body>)!$content!i;
return $chunk;
};
}
});
}
1;
__END__
=head1 NAME
Plack::Middleware::Debug - display information about the current request/response
=head1 SYNOPSIS
enable "Debug";
=head1 DESCRIPTION
The debug middleware offers a configurable set of panels that displays
information about the current request and response. The information is
generated only for responses with a status of 200 (C<OK>) and a
C<Content-Type> that contains C<text/html> or C<application/xhtml+xml>
and is embedded in the HTML that is sent back to the browser. Also the
code is injected directly before the C<< </body> >> tag so if there is
no such tag, the information will not be injected.
To enable the middleware, just use L<Plack::Builder> as usual in your C<.psgi>
file:
use Plack::Builder;
builder {
enable 'Debug', panels => [ qw(DBITrace Memory Timer) ];
$app;
};
The C<Debug> middleware takes an optional C<panels> argument whose value is
expected to be a reference to an array of panel specifications. If given,
only those panels will be enabled. If you don't pass a C<panels>
argument, the default list of panels - C<Environment>, C<Response>,
C<Timer>, C<Memory>, C<Session> and C<DBITrace> - will be enabled, each with
their default settings, and automatically disabled if their targer modules or
middleware components are not loaded.
Each panel specification can take one of three forms:
=over 4
=item A string
This is interpreted as the base name of a panel in the
C<Plack::Middeware::Debug::> namespace. The panel class is loaded and a panel
object is created with its default settings.
=item An array reference
If you need to pass arguments to the panel object as it is created,
you may use this form (But see below).
The first element of the array reference has to be the panel base
name. The remaining elements are key/value pairs to be passed to the
panel.
For example:
builder {
enable 'Debug', panels =>
[ qw(Environment Response Timer Memory),
[ 'DBITrace', level => 2 ]
];
$app;
};
Because each panel is a middleware component, you can write this way
as well:
builder {
enable 'Debug'; # load defaults
enable 'Debug::DBITrace', level => 2;
$app;
};
Note that the C<<enable 'Debug'>> line should come before other Debug
panels because of the order middleware components are executed.
=item Custom middleware
You can also pass a Panel middleware component. This might be useful
if you have custom debug panels in your framework or web application.
=back
=head1 HOW TO WRITE YOUR OWN DEBUG PANEL
The C<Debug> middleware is designed to be easily extensible. You might
want to write a custom debug panel for your framework or for your web
application. Each debug panel is also a Plack middleware copmonent and
is easy to write one.
Let's look at the anatomy of the C<Timer> debug panel. Here is the code from
that panel:
package Plack::Middleware::Debug::Timer;
use Time::HiRes;
use parent qw(Plack::Middleware::Debug::Base);
sub run {
my($self, $env, $panel) = @_;
my $start = [ Time::HiRes::gettimeofday ];
return sub {
my $res = shift;
my $end = [ Time::HiRes::gettimeofday ];
my $elapsed = sprintf '%.6f s', Time::HiRes::tv_interval $start, $end;
$panel->nav_subtitle($elapsed);
$panel->content(
$self->render_list_pairs(
[ Start => $self->format_time($start),
End => $self->format_time($end),
Elapsed => $elapsed ],
),
);
};
}
sub format_time { ... }
To write a new debug panel, place it in the C<Plack::Middleware::Debug::>
namespace. In our example, the C<Timer> panel lives in the
C<Plack::Middleware::Debug::Timer> package.
The only thing your panel should do is to subclass
L<Plack::Middleware::Debug::Base>. This does most of the things a
middleware component should do as a Plack middleware, so you only need
to override C<run> method to profile and create the panel content.
sub run {
my($self, $env, $panel) = @_;
# Do something before the application runs
return sub {
my $res = shift;
# Do something after the application returns
};
}
You can create as many lexical variables as you need and reference
that in the returned callback as a closure, and update the content of
of the C<$panel> which is Plack::Middleware::Debug::Panel object.
In our C<Timer> example we want to list three key/value pairs: the
start time, the end time and the elapsed time. We use the
C<render_list_pairs()> method to place the pairs in the order we
want. There is also a C<render_hash()> and C<render_lines()> method,
to render a hash keys and values, as well as just text lines (e.g. log
messages).
=head1 BUGS AND LIMITATIONS
Please report any bugs or feature requests through the web interface at
L<http://rt.cpan.org>.
=head1 INSTALLATION
See perlmodinstall for information and options on installing Perl modules.
=head1 AVAILABILITY
The latest version of this module is available from the Comprehensive Perl
Archive Network (CPAN). Visit L<http://www.perl.com/CPAN/> to find a CPAN site
near you. Or see L<http://search.cpan.org/dist/Plack-Middleware-Debug/>.
The development version lives at
L<http://github.com/miyagawa/plack-middleware-debug/>. Instead of sending
patches, please fork this project using the standard git and github
infrastructure.
=head1 AUTHORS
Marcel Grunauer, C<< <marcel@cpan.org> >>
Tatsuhiko Miyagawa, C<< <miyagawa@bulknews.net> >>
=head1 COPYRIGHT AND LICENSE
Copyright 2009 by Marcel GrE<uuml>nauer
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=head1 SEE ALSO
The debug middleware is heavily influenced (that is, adapted from) the Django
Debug Toolbar - see L<http://github.com/robhudson/django-debug-toolbar>.
=cut
|