HEX
Server: Apache
System: Linux s198.coreserver.jp 5.15.0-151-generic #161-Ubuntu SMP Tue Jul 22 14:25:40 UTC 2025 x86_64
User: nagasaki (10062)
PHP: 7.1.33
Disabled: NONE
Upload Files
File: //usr/local/share/man/man3/Plack::Builder.3pm
.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings.  \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
.    ds -- \(*W-
.    ds PI pi
.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
.    ds L" ""
.    ds R" ""
.    ds C` ""
.    ds C' ""
'br\}
.el\{\
.    ds -- \|\(em\|
.    ds PI \(*p
.    ds L" ``
.    ds R" ''
.    ds C`
.    ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD.  Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{\
.    if \nF \{\
.        de IX
.        tm Index:\\$1\t\\n%\t"\\$2"
..
.        if !\nF==2 \{\
.            nr % 0
.            nr F 2
.        \}
.    \}
.\}
.rr rF
.\" ========================================================================
.\"
.IX Title "Plack::Builder 3"
.TH Plack::Builder 3 "2020-11-30" "perl v5.26.3" "User Contributed Perl Documentation"
.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
Plack::Builder \- OO and DSL to enable Plack Middlewares
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
.Vb 2
\&  # 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(\*(AqFoo\*(Aq, opt => 1);
\&  $builder\->add_middleware(\*(AqBar\*(Aq);
\&  $builder\->wrap($app);
.Ve
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
Plack::Builder gives you a quick domain specific language (\s-1DSL\s0) to
wrap your application with Plack::Middleware subclasses. The
middleware you're trying to use should use Plack::Middleware as a
base class to use this \s-1DSL,\s0 inspired by Rack::Builder.
.PP
Whenever you call \f(CW\*(C`enable\*(C'\fR 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. \f(CW"Plack::Middleware::"\fR
is added as a prefix by default. So:
.PP
.Vb 5
\&  builder {
\&      enable "Foo";
\&      enable "Bar", opt => "val";
\&      $app;
\&  };
.Ve
.PP
is syntactically equal to:
.PP
.Vb 2
\&  $app = Plack::Middleware::Bar\->wrap($app, opt => "val");
\&  $app = Plack::Middleware::Foo\->wrap($app);
.Ve
.PP
In other words, you're supposed to \f(CW\*(C`enable\*(C'\fR middleware from outer to inner.
.SH "INLINE MIDDLEWARE"
.IX Header "INLINE MIDDLEWARE"
Plack::Builder allows you to code middleware inline using a nested
code reference.
.PP
If the first argument to \f(CW\*(C`enable\*(C'\fR is a code reference, it will be
passed an \f(CW$app\fR and should return another code reference
which is a \s-1PSGI\s0 application that consumes \f(CW$env\fR at runtime. So:
.PP
.Vb 10
\&  builder {
\&      enable sub {
\&          my $app = shift;
\&          sub {
\&              my $env = shift;
\&              # do preprocessing
\&              my $res = $app\->($env);
\&              # do postprocessing
\&              return $res;
\&          };
\&      };
\&      $app;
\&  };
.Ve
.PP
is equal to:
.PP
.Vb 4
\&  my $mw = sub {
\&      my $app = shift;
\&      sub { my $env = shift; $app\->($env) };
\&  };
\&
\&  $app = $mw\->($app);
.Ve
.SH "URLMap support"
.IX Header "URLMap support"
Plack::Builder has a native support for Plack::App::URLMap via the \f(CW\*(C`mount\*(C'\fR method.
.PP
.Vb 8
\&  use Plack::Builder;
\&  my $app = builder {
\&      mount "/foo" => $app1;
\&      mount "/bar" => builder {
\&          enable "Foo";
\&          $app2;
\&      };
\&  };
.Ve
.PP
See Plack::App::URLMap's \f(CW\*(C`map\*(C'\fR method to see what they mean. With
\&\f(CW\*(C`builder\*(C'\fR you can't use \f(CW\*(C`map\*(C'\fR as a \s-1DSL,\s0 for the obvious reason :)
.PP
\&\fB\s-1NOTE\s0\fR: Once you use \f(CW\*(C`mount\*(C'\fR in your builder code, you have to use
\&\f(CW\*(C`mount\*(C'\fR for all the paths, including the root path (\f(CW\*(C`/\*(C'\fR). You can't
have the default app in the last line of \f(CW\*(C`builder\*(C'\fR like:
.PP
.Vb 4
\&  my $app = sub {
\&      my $env = shift;
\&      ...
\&  };
\&
\&  builder {
\&      mount "/foo" => sub { ... };
\&      $app; # THIS DOESN\*(AqT WORK
\&  };
.Ve
.PP
You'll get warnings saying that your mount configuration will be
ignored. Instead you should use \f(CW\*(C`mount "/" => ...\*(C'\fR in the last
line to set the default fallback app.
.PP
.Vb 4
\&  builder {
\&      mount "/foo" => sub { ... };
\&      mount "/" => $app;
\&  }
.Ve
.PP
Note that the \f(CW\*(C`builder\*(C'\fR \s-1DSL\s0 returns a whole new \s-1PSGI\s0 application, which means
.IP "\(bu" 4
\&\f(CW\*(C`builder { ... }\*(C'\fR should normally the last statement of a \f(CW\*(C`.psgi\*(C'\fR
file, because the return value of \f(CW\*(C`builder\*(C'\fR is the application that
is actually executed.
.IP "\(bu" 4
You can nest your \f(CW\*(C`builder\*(C'\fR blocks, mixed with \f(CW\*(C`mount\*(C'\fR statements (see \*(L"URLMap support\*(R"
above):
.Sp
.Vb 5
\&  builder {
\&      mount "/foo" => builder {
\&          mount "/bar" => $app;
\&      }
\&  }
.Ve
.Sp
will locate the \f(CW$app\fR under \f(CW\*(C`/foo/bar\*(C'\fR, since the inner \f(CW\*(C`builder\*(C'\fR
block puts it under \f(CW\*(C`/bar\*(C'\fR and it results in a new \s-1PSGI\s0 application
which is located under \f(CW\*(C`/foo\*(C'\fR because of the outer \f(CW\*(C`builder\*(C'\fR block.
.SH "CONDITIONAL MIDDLEWARE SUPPORT"
.IX Header "CONDITIONAL MIDDLEWARE SUPPORT"
You can use \f(CW\*(C`enable_if\*(C'\fR to conditionally enable middleware based on
the runtime environment.
.PP
.Vb 4
\&  builder {
\&      enable_if { $_[0]\->{REMOTE_ADDR} eq \*(Aq127.0.0.1\*(Aq } \*(AqStackTrace\*(Aq, force => 1;
\&      $app;
\&  };
.Ve
.PP
See Plack::Middleware::Conditional for details.
.SH "OBJECT ORIENTED INTERFACE"
.IX Header "OBJECT ORIENTED INTERFACE"
Object oriented interface supports the same functionality with the \s-1DSL\s0
version in a clearer interface, probably with more typing required.
.PP
.Vb 6
\&  # With mount
\&  my $builder = Plack::Builder\->new;
\&  $builder\->add_middleware(\*(AqFoo\*(Aq, opt => 1);
\&  $builder\->mount(\*(Aq/foo\*(Aq => $foo_app);
\&  $builder\->mount(\*(Aq/\*(Aq => $root_app);
\&  $builder\->to_app;
\&
\&  # Nested builders. Equivalent to:
\&  # builder {
\&  #     mount \*(Aq/foo\*(Aq => builder {
\&  #         enable \*(AqFoo\*(Aq;
\&  #         $app;
\&  #     };
\&  #     mount \*(Aq/\*(Aq => $app2;
\&  # };
\&  my $builder_out = Plack::Builder\->new;
\&  my $builder_in  = Plack::Builder\->new;
\&  $builder_in\->add_middleware(\*(AqFoo\*(Aq);
\&  $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 \*(Aq127.0.0.1\*(Aq }, \*(AqStackTrace\*(Aq);
\&  $builder\->wrap($app);
.Ve
.SH "SEE ALSO"
.IX Header "SEE ALSO"
Plack::Middleware Plack::App::URLMap Plack::Middleware::Conditional