---
name: "Plack::Middleware"
section: "3pm"
platform: "linux"
package: "libplack-perl"
version: "1.0051-1"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/Plack::Middleware"
---

# Plack::Middleware(3pm)

Base class for easy-to-use PSGI middleware

## NAME

Plack::Middleware - Base class for easy-to-use PSGI middleware

## SYNOPSIS

```
  package Plack::Middleware::Foo;
  use parent qw( Plack::Middleware );
  sub call {
      my($self, $env) = @_;
      # Do something with $env
      # $self->app is the original app
      my $res = $self->app->($env);
      # Do something with $res
      return $res;
  }
  # then in app.psgi
  use Plack::Builder;
  my $app = sub { ... } # as usual
  builder {
      enable "Plack::Middleware::Foo";
      enable "Plack::Middleware::Bar", %options;
      $app;
  };
```

## DESCRIPTION

Plack::Middleware is a utility base class to write PSGI middleware. All you have to do is to inherit from Plack::Middleware and then implement the callback `"call"` method (or the `"to_app"` method that would return the PSGI code reference) to do the actual work. You can use `"$self->app"` to call the original (wrapped) application.

Your middleware object is created at the PSGI application compile time and is persistent during the web server life cycle (unless it is a non-persistent environment such as CGI), so you should never set or cache per-request data like `$env` in your middleware object. See also "OBJECT LIFECYCLE" in Plack::Component.

See Plack::Builder how to actually enable middleware in your *.psgi* application file using the DSL. If you do not like our builder DSL, you can also use the `"wrap"` method to wrap your application with a middleware:

```
  use Plack::Middleware::Foo;
  my $app = sub { ... };
  $app = Plack::Middleware::Foo->wrap($app, %options);
  $app = Plack::Middleware::Bar->wrap($app, %options);
```

## RESPONSE CALLBACK

The typical middleware is written like this:

```
  package Plack::Middleware::Something;
  use parent qw(Plack::Middleware);
  sub call {
      my($self, $env) = @_;
      # pre-processing $env
      my $res = $self->app->($env);
      # post-processing $res
      return $res;
  }
```

The tricky thing about post-processing the response is that it could either be an immediate 3 element array ref, or a code reference that implements the delayed (streaming) interface.

Dealing with these two types of response in each piece of middleware is pointless, so you're recommended to use the `"response_cb"` wrapper function in Plack::Util when implementing a post processing middleware.

```
  sub call {
      my($self, $env) = @_;
      # pre-processing $env
      my $res = $self->app->($env);
      return Plack::Util::response_cb($res, sub {
          my $res = shift;
          # do something with $res;
      });
  }
```

The callback function gets a response as an array reference, and you can update the reference to implement the post-processing. In the normal case, this arrayref will have three elements (as described by the PSGI spec), but will have only two elements when using a `$writer` as described below.

```
  package Plack::Middleware::Always500;
  use parent qw(Plack::Middleware);
  use Plack::Util;
  sub call {
      my($self, $env) = @_;
      my $res  = $self->app->($env);
      return Plack::Util::response_cb($res, sub {
          my $res = shift;
          $res->[0] = 500;
          return;
      });
  }
```

In this example, the callback gets the `$res` and updates its first element (status code) to 500. Using `"response_cb"` makes sure that this works with the delayed response too.

You're not required (and not recommended either) to return a new array reference - they will be simply ignored. You're suggested to explicitly return, unless you fiddle with the content filter callback (see below).

Similarly, note that you have to keep the `$res` reference when you swap the entire response.

```
  Plack::Util::response_cb($res, sub {
      my $res = shift;
      $res = [ $new_status, $new_headers, $new_body ]; # THIS DOES NOT WORK
      return;
  });
```

This does not work, since assigning a new anonymous array to `$res` doesn't update the original PSGI response value. You should instead do:

```
  Plack::Util::response_cb($res, sub {
      my $res = shift;
      @$res = ($new_status, $new_headers, $new_body); # THIS WORKS
      return;
  });
```

The third element of the response array ref is a body, and it could be either an arrayref or IO::Handle-ish object. The application could also make use of the `$writer` object if `"psgi.streaming"` is in effect, and in this case, the third element will not exist (`"@$res == 2"`). Dealing with these variants is again really painful, and `"response_cb"` can take care of that too, by allowing you to return a content filter as a code reference.

```
  # replace all "Foo" in content body with "Bar"
  Plack::Util::response_cb($res, sub {
      my $res = shift;
      return sub {
          my $chunk = shift;
          return unless defined $chunk;
          $chunk =~ s/Foo/Bar/g;
          return $chunk;
      }
  });
```

The callback takes one argument `$chunk` and your callback is expected to return the updated chunk. If the given `$chunk` is undef, it means the stream has reached the end, so your callback should also return undef, or return the final chunk and return undef when called next time.

## SEE ALSO

Plack Plack::Builder Plack::Component
