Plack 代码和结构分析-PSGI Application Architecture[译]
PSGI Applications
在 PSGI spec 中定义了有关 PSGI 的应用相关的内容.
PSGI 应用是一个 Perl 代码块的引用. 它需要一个参数, 环境变量, 并返回一个包含着三个值的数组.
这三个值是 HTTP 的状态 status, 响应的 header, 和 body. 下面是一个简单的例子:
my$app= sub{ my$env= shift; return[ '200', [ 'Content-Type'=> 'text/plain'], [ "Hello World"], # or IO::Handle-like object ]; };
PSGI 环境变量的哈希
PSGI 环境变量的哈希是一个有很多键的哈希引用. 它主要是这些 (headers, body, etc), 都是从 HTTP::Request 解析并放到这个哈希中来给方便访问.
中间件
中间件会取得 PSGI 的应用, 并运行和传送 PSGI 的环境变量的哈希给它. 它在运行 PSGI 的应用之前, 如果有需要, 它可能会修改环境变量. 并且在运行完应用之后, 它也可能修改响应的内容.
Plack::Middleware
中间件是围绕在 PSGI 的应用上来封装的. 应用可以被一个或者多个中间件包围封装, 这样可以创建一层又一层就象洋葱 onion. 事件驱动和回调让中间件有着不同寻常的结构.
所有的中间件都继承 Plack::Middleware. 它是一个非常小的模块. 这个中间件模块只有 2 个很短的子函数 (注意 call() 和 prepare_app()这二个函数是由使用者来完成):
译注: 现在其实只有一个 wrap 函数了. 其中 to_app 现在是在 Plack::Component 模块中实现. to_app 是用于返回代码块.
subwrap { my($self, $app, @args) = @_; if(ref$self) { $self->{app} = $app; } else{ $self= $self->new({ app => $app, @args}); } return$self->to_app; } subto_app { my$self= shift; $self->prepare_app; returnsub{ $self->call(@_) }; }
这些函数是怎么样在一起工作的? 这些中间件的洋葱结构决定了, 可以这样构造:
my$app= MyWebApp->new->to_app; $app= Plack::Middleware::A->wrap($app); $app= Plack::Middleware::B->wrap($app); $app= Plack::Middleware::C->wrap($app);
象下面这样写, 可能更加清楚和容易让你明白
my$app0= MyWebApp->new->to_app; # $app0->($env) 运行 web app $app1= Plack::Middleware::A->wrap($app0); # $app1->($env) 调用 P::M::A->call() 这是 $app0->($env) $app2= Plack::Middleware::B->wrap($app1); # $app2->($env) 调用 P::M::B->call() 这是 $app1->($env) $app3= Plack::Middleware::C->wrap($app2); # $app3->($env) 调用 P::M::C->call() 这是 $app2->($env) # 当服务器收到一个请求时调用 $app3->($env)
当有新的事件发生时 - 例如, PSGI 的服务器收到一个新的请求 — 它传送这个事件给应用 app. 这个 app 是链式回调来运行每个. 这显然就是事件驱动编程的例子.
Plack::Component 和 Plack::App
Plack::Middleware 继承自 Plack::Component.所以中间件也是使用了 Plack::Component 中的东西.
Plack::Component 是用于创建 PSGI 应用的工具. 它也是很轻量一层的代码, 它主要是用于 Plack::App 名字空间的一些模块实现用的接口. Plack::App::File 是一个 Web 服务器, 用于实现指定目录的静态文件输出,Plack::App::URLMap 是用于给多个 url 指向不同的应用.
但注意, 我们并不需要在我们的 PSGI 的应用中来指定来 use Plack::Component . 一个 PSGI 的应用只是一个代码块的引用. 这个 PSGI spec 没有讲 PSGI 的应用需要继承 Plack::Component.
我们使用 Plack::Component 提供的接口来在自己创建的应用中使用这些接口. 当我们见到 $app 时, 我们就可以使用这些行为, 这显然看起来就象中间件, 但从设计的角度来讲, 分离开来比较好.
不过这个东西不是在我们的应用中必须的, 它会增加我们的复杂性.
建议继续学习:
- Plack 代码和结构分析一[译] (阅读:945)
- Plack 代码和结构分析-Plack::Builder[译] (阅读:621)
- Plack 代码和结构分析-plackup Architecture[译] (阅读:587)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:扶 凯 来源: 扶凯
- 标签: Plack
- 发布时间:2015-02-26 22:29:04
- [54] IOS安全–浅谈关于IOS加固的几种方法
- [52] android 开发入门
- [52] 如何拿下简短的域名
- [51] 图书馆的世界纪录
- [49] Go Reflect 性能
- [49] Oracle MTS模式下 进程地址与会话信
- [47] 【社会化设计】自我(self)部分――欢迎区
- [46] 读书笔记-壹百度:百度十年千倍的29条法则
- [36] 程序员技术练级攻略
- [29] 视觉调整-设计师 vs. 逻辑