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

caj*_*ine 5 perl plack

如果我理解正确,PSGI应用程序将作为下一个:

  • 得到了浏览器的请求
  • 通过顺序中的某些中间件,请求是"气泡",因为它们是在中定义的 builder
  • 请求来到我的应用程序
  • 我的应用程序产生一些响应
  • 这通过一些中间件再次响应泡沫
  • 最后将响应发送到浏览器

当请求登陆我的时,我可以轻松地调试打印所有标题(例如cookie)$app.

问题是: 如何调试 - 打印实际状态,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
}
Run Code Online (Sandbox Code Playgroud)

它可能不像是那样容易,

print STDERR Dumper $dont_know_what->request->headers(); #HTTP::Headers ???
print STDERR Dumper $dont_know_what->respond->headers();
Run Code Online (Sandbox Code Playgroud)

所以加一个赏金:);)

ben*_*kah 5

一种基本方法是创建一个中间件,在执行包装的应用程序之前转储标头,然后在执行之后转储标头。然后,您可以在想要查看标头的每个点启用此中间件,正如您在伪代码中指出的那样。

以下代码通过在每次启用它时构建一个内联中间件来实现此目的。

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' ] ];
  }}
};
Run Code Online (Sandbox Code Playgroud)

当我使用 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)"
Run Code Online (Sandbox Code Playgroud)

显然,您可以将其变成像 Ashley 那样的实际中间件,并且您可能需要对其进行调整以使用您拥有的任何设施发送日志消息。


Ash*_*ley 2

中间件

\n\n
package ShowMeTheHeaders;\nuse parent "Plack::Middleware";\nuse Plack::Request;\nuse Plack::Response\nrequire Text::Wrap;\n\nmy $_call_back = sub {\n    my $response = Plack::Response->new(@{+shift});\n    print "* Response Headers:\\n",\n        Text::Wrap::wrap("\\t", "\\t", $response->headers->as_string);\n    return; # Explicit return suggested by docs.\n};\n\nsub call {\n    my $self = shift;\n    my $request = Plack::Request->new(shift);\n    print "* Request Headers:\\n",\n        Text::Wrap::wrap("\\t", "\\t", $request->headers->as_string);\n    my $response = $self->app->($request);\n    Plack::Util::response_cb($response, $_call_back);\n}\n\n1;\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以在没有对象化(Plack::RequestPlack::Response)的情况下执行此操作,但随后您必须处理标头字段的原始属性和键,而不是完全更令人愉快的->as_string另请参阅Plack::Middleware的 \xe2\x80\x9cresponse 回调\xe2\x80\x9d 部分。

\n\n

演示 PSGI

\n\n
use warnings;\nuse strict;\nuse Plack::Builder;\n\nmy $app = sub {\n    [ 200,\n      [ "Content-Type" => "text/plain" ],\n      [ "O HAI, PLAK!" ]\n    ];\n};\n\nbuilder {\n    enable "+ShowMeTheHeaders";\n    mount "/" => $app;\n};\n
Run Code Online (Sandbox Code Playgroud)\n