取势 明道 优术

作者为 扶 凯 发表

昨天我们看到一个非常简单有效的使用中间件组件的例子.这次我们加入一个基本的 HTTP 的功能 JSONP.
JSONP (JSON-Padding) 是一个非官方的协议,它允许在服务器端使用 JSON 给来给客户端的 javascript callback 进行访问.这可以跨域通过基本 JSON 来包含访问的 HTML script tags 的内容


Middleware::JSONP

假定你的 Web 应用返回 JSON 的编码数据,Content-Type 是 application/json.然后 PSGI 的应用:

use JSON;
my $app = sub {
    my $env = shift;
    if ($env->{PATH_INFO} eq '/whatever.json') {
        my $body = JSON::encode_json({
            hello => 'world',
        });
        return [ 200, ['Content-Type', 'application/json'], [ $body ] ];
    }
    return [ 404, ['Content-Type', 'text/html'], ['Not Found']];
};

 

加入 JSONP 的支持非常简单,只要使用 Middleware::JSONP:

use Plack::Builder;
builder {
    enable "JSONP";
    $app;
};

他只是一行就完成这个功能.这个中间件检查 response 的内容为 application/json and.如果请求的是 "/whatever.json" 连接后返回标准的 JSON ,但请求 "/whatever.json?callback=myCallback" 会返回

myCallback({"hello":"world"});

和 Content-Type text/javascript. Content-Length 是会自动的输出的.

框架中怎么应用
JSONP 除了支持JSON, 能完成大多数框架做的相当琐碎的事,因为 Middleware::JSONP 是放在 Plack 的中间件那层,所以没有多少复杂的东西.
所以, JSONP 中间件应该能工作在任何 Web 框架的 JSON 的输出上,象 Catalyst:

package MyApp::View::JSON;
use base qw( Catalyst::View::JSON );

package MyApp::Controller::Foo;
sub hello : Local {
    my($self, $c) = @_;
    $c->stash->{message} = 'Hello World!';
    $c->forward('MyApp::View::JSON');
}

如果使用了 Catalyst::Engine::PSGI 和 Plack::Builder 你要支持 JSONP 的支持控制,如下

use MyApp;
MyApp->setup_engine('PSGI');
my $app = sub { MyApp->run(@_) };

use Plack::Builder;
builder {
    enable "JSONP";
    $app;
};

很意外,Catalyst::View::JSON 是我写的模块,默认支持 JSONP 回调的配置,但是有不止一种方法来做到这一点!

 

 这是译文,原文地址:http://advent.plackperl.org/2009/12/day-16-adding-jsonp-support-to-your-app.html

来了就留个评论吧! 没有评论