窥探不同plack中间件之间的http报头



如果我理解正确的话,PSGI应用程序如下:

  • 从浏览器获得请求
  • 请求是按照builder
  • 中定义的顺序通过一些中间件的"气泡"。
  • 请求到达我的应用
  • 我的应用程序产生一些响应
  • 此响应再次通过一些中间件起泡
  • 最后将响应发送到浏览器

当请求到达我的$app时,我可以很容易地调试打印所有头(例如cookies)。

问题是:如何调试打印headers的实际状态,而请求通过许多中间件来我的应用程序,而响应是再次通过中间件出去。

所以,有一个(简化的)app.psgi,就像下面的:

use strict;
use warnings;
use Plack::Builder;
my $app = sub { ... };
builder {
         # <- debug-print the first request headers
         #                and the last respond headers here
    enable "Debug";
         # <- debug-print the actual state of request/respond headers here
    enable "mid2";
         # <- and here
    enable "mid3";
         # <- and here
    $app; # <- and finally here - this is of course EASY
}

这可能不像这样简单,

print STDERR Dumper $dont_know_what->request->headers(); #HTTP::Headers ???
print STDERR Dumper $dont_know_what->respond->headers();

所以添加赏金:);)

一种基本方法是创建一个中间件,在执行包装后的应用程序之前和之后转储报头。然后,在您希望看到您在伪代码中指出的头的每个点启用此中间件。

下面的代码通过在每次启用时构建一个内联中间件来实现这一点。

use Plack::Builder;
use Plack::Request;
use Plack::Response;
sub headers_around {
  my $position = shift;
  # build and return the headers_around middleware as a closure
  return sub {
    my $app = shift;
    # gets called each request
    return sub {
      my $env = shift;
      my $req = Plack::Request->new($env);
      # display headers before next middleware
      print STDERR "req headers before $position:n" . $req->headers->as_string . "n=====n";
      # execute the next app on the stack
      my $res = $app->($env);
      my $response = Plack::Response->new(@$res);
      # display headers after previous middleware
      print STDERR "res headers after $position:n" . $response->headers->as_string . "n=====n";
      return $res;
    };
  };
};
builder {
  enable headers_around('Debug');
  enable 'Debug';
  enable headers_around('Lint');
  enable 'Lint';
  enable headers_around('StackTrace');
  enable 'StackTrace', force => 1;
  enable headers_around('App');
  mount '/' => builder { sub {
    return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ];
  }}
};
# now build the application enabling regular middleware with our inline middleware
builder {
  enable headers_around('Debug');
  enable 'Debug';
  enable headers_around('Lint');
  enable 'Lint';
  enable headers_around('StackTrace');
  enable 'StackTrace', force => 1;
  enable headers_around('App');
  mount '/' => builder { sub {
        return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ];
  }}
};

当我用plackup运行它时,我得到以下输出:

$ plackup --app between_middleware.psgi
HTTP::Server::PSGI: Accepting connections at http://0:5000/
req headers before Debug:
Connection: Keep-Alive
Accept: */*
Host: 0:5000
User-Agent: Wget/1.12 (linux-gnu)
=====
req headers before Lint:
Connection: Keep-Alive
Accept: */*
Host: 0:5000
User-Agent: Wget/1.12 (linux-gnu)
=====
req headers before StackTrace:
Connection: Keep-Alive
Accept: */*
Host: 0:5000
User-Agent: Wget/1.12 (linux-gnu)
=====
req headers before App:
Connection: Keep-Alive
Accept: */*
Host: 0:5000
User-Agent: Wget/1.12 (linux-gnu)
=====
res headers after App:
Content-Type: text/plain
=====
res headers after StackTrace:
Content-Type: text/plain
=====
res headers after Lint:
Content-Type: text/plain
=====
res headers after Debug:
Content-Type: text/plain
=====
127.0.0.1 - - [02/Apr/2014:19:37:30 -0700] "GET / HTTP/1.0" 200 11 "-" "Wget/1.12 (linux-gnu)"

显然,你可以把它变成一个实际的中间件,像阿什利的,你可能不得不调整它发送日志消息使用任何设施,你已经在适当的

中间件

package ShowMeTheHeaders;
use parent "Plack::Middleware";
use Plack::Request;
use Plack::Response
require Text::Wrap;
my $_call_back = sub {
    my $response = Plack::Response->new(@{+shift});
    print "* Response Headers:n",
        Text::Wrap::wrap("t", "t", $response->headers->as_string);
    return; # Explicit return suggested by docs.
};
sub call {
    my $self = shift;
    my $request = Plack::Request->new(shift);
    print "* Request Headers:n",
        Text::Wrap::wrap("t", "t", $request->headers->as_string);
    my $response = $self->app->($request);
    Plack::Util::response_cb($response, $_call_back);
}
1;

您可以在没有对象化(Plack::Request和Plack::Response)的情况下做到这一点,但是您必须处理报头字段的原始属性和键,而不是完全更令人愉快的->as_string。参见Plack::Middleware的" response callback "部分。

演示psgi

use warnings;
use strict;
use Plack::Builder;
my $app = sub {
    [ 200,
      [ "Content-Type" => "text/plain" ],
      [ "O HAI, PLAK!" ]
    ];
};
builder {
    enable "+ShowMeTheHeaders";
    mount "/" => $app;
};

相关内容

  • 没有找到相关文章

最新更新