This file is indexed.

/usr/share/perl5/Plack/Builder.pm is in libplack-perl 1.0033-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
package Plack::Builder;
use strict;
use parent qw( Exporter );
our @EXPORT = qw( builder add enable enable_if mount );

use Carp ();
use Plack::App::URLMap;
use Plack::Middleware::Conditional; # TODO delayed load?
use Scalar::Util ();

sub new {
    my $class = shift;
    bless { middlewares => [ ] }, $class;
}

sub add_middleware {
    my($self, $mw, @args) = @_;

    if (ref $mw ne 'CODE') {
        my $mw_class = Plack::Util::load_class($mw, 'Plack::Middleware');
        $mw = sub { $mw_class->wrap($_[0], @args) };
    }

    push @{$self->{middlewares}}, $mw;
}

sub add_middleware_if {
    my($self, $cond, $mw, @args) = @_;

    if (ref $mw ne 'CODE') {
        my $mw_class = Plack::Util::load_class($mw, 'Plack::Middleware');
        $mw = sub { $mw_class->wrap($_[0], @args) };
    }

    push @{$self->{middlewares}}, sub {
        Plack::Middleware::Conditional->wrap($_[0], condition => $cond, builder => $mw);
    };
}

# do you want remove_middleware() etc.?

sub _mount {
    my ($self, $location, $app) = @_;

    if (!$self->{_urlmap}) {
        $self->{_urlmap} = Plack::App::URLMap->new;
    }

    $self->{_urlmap}->map($location => $app);
    $self->{_urlmap}; # for backward compat.
}

sub to_app {
    my($self, $app) = @_;

    if ($app) {
        $self->wrap($app);
    } elsif ($self->{_urlmap}) {
        $self->{_urlmap} = $self->{_urlmap}->to_app
            if Scalar::Util::blessed($self->{_urlmap});
        $self->wrap($self->{_urlmap});
    } else {
        Carp::croak("to_app() is called without mount(). No application to build.");
    }
}

sub wrap {
    my($self, $app) = @_;

    if ($self->{_urlmap} && $app ne $self->{_urlmap}) {
        Carp::carp("WARNING: wrap() and mount() can't be used altogether in Plack::Builder.\n" .
                   "WARNING: This causes all previous mount() mappings to be ignored.");
    }

    for my $mw (reverse @{$self->{middlewares}}) {
        $app = $mw->($app);
    }

    $app;
}

# DSL goes here
our $_add = our $_add_if = our $_mount = sub {
    Carp::croak("enable/mount should be called inside builder {} block");
};

sub enable         { $_add->(@_) }
sub enable_if(&$@) { $_add_if->(@_) }

sub mount {
    my $self = shift;
    if (Scalar::Util::blessed($self)) {
        $self->_mount(@_);
    }else{
        $_mount->($self, @_);
    }
}

sub builder(&) {
    my $block = shift;

    my $self = __PACKAGE__->new;

    my $mount_is_called;
    my $urlmap = Plack::App::URLMap->new;
    local $_mount = sub {
        $mount_is_called++;
        $urlmap->map(@_);
        $urlmap;
    };
    local $_add = sub {
        $self->add_middleware(@_);
    };
    local $_add_if = sub {
        $self->add_middleware_if(@_);
    };

    my $app = $block->();

    if ($mount_is_called) {
        if ($app ne $urlmap) {
            Carp::carp("WARNING: You used mount() in a builder block, but the last line (app) isn't using mount().\n" .
                       "WARNING: This causes all mount() mappings to be ignored.\n");
        } else {
            $app = $app->to_app;
        }
    }

    $app = $app->to_app if $app and Scalar::Util::blessed($app) and $app->can('to_app');

    $self->to_app($app);
}

1;

__END__

=head1 NAME

Plack::Builder - OO and DSL to enable Plack Middlewares

=head1 SYNOPSIS

  # in .psgi
  use Plack::Builder;

  my $app = sub { ... };

  builder {
      enable "Deflater";
      enable "Session", store => "File";
      enable "Debug", panels => [ qw(DBITrace Memory Timer) ];
      enable "+My::Plack::Middleware";
      $app;
  };

  # use URLMap

  builder {
      mount "/foo" => builder {
          enable "Foo";
          $app;
      };

      mount "/bar" => $app2;
      mount "http://example.com/" => builder { $app3 };
  };

  # using OO interface
  my $builder = Plack::Builder->new;
  $builder->add_middleware('Foo', opt => 1);
  $builder->add_middleware('Bar');
  $builder->wrap($app);

=head1 DESCRIPTION

Plack::Builder gives you a quick domain specific language (DSL) to
wrap your application with L<Plack::Middleware> subclasses. The
middleware you're trying to use should use L<Plack::Middleware> as a
base class to use this DSL, inspired by Rack::Builder.

Whenever you call C<enable> on any middleware, the middleware app is
pushed to the stack inside the builder, and then reversed when it
actually creates a wrapped application handler. C<"Plack::Middleware::">
is added as a prefix by default. So:

  builder {
      enable "Foo";
      enable "Bar", opt => "val";
      $app;
  };

is syntactically equal to:

  $app = Plack::Middleware::Bar->wrap($app, opt => "val");
  $app = Plack::Middleware::Foo->wrap($app);

In other words, you're supposed to C<enable> middleware from outer to inner.

=head1 INLINE MIDDLEWARE

Plack::Builder allows you to code middleware inline using a nested
code reference.

If the first argument to C<enable> is a code reference, it will be
passed an C<$app> and should return another code reference
which is a PSGI application that consumes C<$env> at runtime. So:

  builder {
      enable sub {
          my $app = shift;
          sub {
              my $env = shift;
              # do preprocessing
              my $res = $app->($env);
              # do postprocessing
              return $res;
          };
      };
      $app;
  };

is equal to:

  my $mw = sub {
      my $app = shift;
      sub { my $env = shift; $app->($env) };
  };

  $app = $mw->($app);

=head1 URLMap support

Plack::Builder has a native support for L<Plack::App::URLMap> via the C<mount> method.

  use Plack::Builder;
  my $app = builder {
      mount "/foo" => $app1;
      mount "/bar" => builder {
          enable "Foo";
          $app2;
      };
  };

See L<Plack::App::URLMap>'s C<map> method to see what they mean. With
C<builder> you can't use C<map> as a DSL, for the obvious reason :)

B<NOTE>: Once you use C<mount> in your builder code, you have to use
C<mount> for all the paths, including the root path (C</>). You can't
have the default app in the last line of C<builder> like:

  my $app = sub {
      my $env = shift;
      ...
  };

  builder {
      mount "/foo" => sub { ... };
      $app; # THIS DOESN'T WORK
  };

You'll get warnings saying that your mount configuration will be
ignored. Instead you should use C<< mount "/" => ... >> in the last
line to set the default fallback app.

  builder {
      mount "/foo" => sub { ... };
      mount "/" => $app;
  }

Note that the C<builder> DSL returns a whole new PSGI application, which means

=over 4

=item *

C<builder { ... }> should normally the last statement of a C<.psgi>
file, because the return value of C<builder> is the application that
is actually executed.

=item *

You can nest your C<builder> blocks, mixed with C<mount> statements (see L</"URLMap support">
above):

  builder {
      mount "/foo" => builder {
          mount "/bar" => $app;
      }
  }

will locate the C<$app> under C</foo/bar>, since the inner C<builder>
block puts it under C</bar> and it results in a new PSGI application
which is located under C</foo> because of the outer C<builder> block.

=back

=head1 CONDITIONAL MIDDLEWARE SUPPORT

You can use C<enable_if> to conditionally enable middleware based on
the runtime environment.

  builder {
      enable_if { $_[0]->{REMOTE_ADDR} eq '127.0.0.1' } 'StackTrace', force => 1;
      $app;
  };

See L<Plack::Middleware::Conditional> for details.

=head1 OBJECT ORIENTED INTERFACE

Object oriented interface supports the same functionality with the DSL
version in a clearer interface, probably with more typing required.

  # With mount
  my $builder = Plack::Builder->new;
  $builder->add_middleware('Foo', opt => 1);
  $builder->mount('/foo' => $foo_app);
  $builder->mount('/' => $root_app);
  $builder->to_app;

  # Nested builders. Equivalent to:
  # builder {
  #     mount '/foo' => builder {
  #         enable 'Foo';
  #         $app;
  #     };
  #     mount '/' => $app2;
  # };
  my $builder_out = Plack::Builder->new;
  my $builder_in  = Plack::Builder->new;
  $builder_in->add_middleware('Foo');
  $builder_out->mount("/foo" => $builder_in->wrap($app));
  $builder_out->mount("/" => $app2);
  $builder_out->to_app;

  # conditional. You can also directly use Plack::Middleware::Conditional
  my $builder = Plack::Builder->new;
  $builder->add_middleware_if(sub { $_[0]->{REMOTE_ADDR} eq '127.0.0.1' }, 'StackTrace');
  $builder->wrap($app);

=head1 SEE ALSO

L<Plack::Middleware> L<Plack::App::URLMap> L<Plack::Middleware::Conditional>

=cut