Search code examples
apacheperlmod-perl2plack

How to intercept reply in Plack/Apache


Given the following handler (straight from https://metacpan.org/pod/Plack::Handler::Apache2)

package My::ModPerl::Handler;
use Plack::Handler::Apache2;

sub get_app {
  # magic!
}

sub handler {
  my $r = shift;       # Apache2::RequestRec
  my $app = get_app(); # CODE
  #-- #(1)
  Plack::Handler::Apache2->call_app($r, $app);
  #-- #(2)
}

and with the app being a black box, is there a way to somehow retrieve the complete response that was generated? I would like to do it in the line marked with #(2) and get both the headers and the body. Ideally, I would do something magical in line #(1) and somehow force $r to store the response (and then retrieve it in #(2)).


Solution

  • You can wrap your app in a middleware that makes the PSGI response available inside your handler code.

    package My::ModPerl::Handler;
    use Plack::Handler::Apache2;
    
    sub get_app {
        # magic!
    }
    
    sub handler {
        my $r   = shift;        # Apache2::RequestRec
        my $app = get_app();    # CODE
    
        my $res;                # this will hold the response
    
        Plack::Handler::Apache2->call_app(
            $r,
            sub {
                my $env = shift;
                $res = $app->($env);    # closes over outside variable
                return $res;
            }
        );
    
        # $res == [ $status, $headers, $body ]
    }
    

    This code closes over $res and assigns the response from inside the application (or rather the extra layer around it). You can then do stuff with it outside the Apache handler code in your own code.

    Please note I've not run this code, but I'm pretty sure it should work.