我们知道不同域中的js代码受同源策略的限制,不同域中的AJAX同样受此限制,不过使用html中的script远程脚本可以跳过该限制,下面我们实际看一下利用RoR和js如何实现所谓的JSONP。
这里只是简单地演示一下功能,并没有严格的实现JSONP,如果是那样需要用一个函数包容JSON对象主体:
some_function([1,2,{a:1,b:11}])
而这里的包容函数名称也不需要定死,而是可以通过http参数告知web服务器,比如可以用以下url的方式:
http://some_address/some_service?arg0=xxx&arg1=xxx&json=some_function
//或者是
http://some_address/some_service?json=some_function
当然这只是一个约定,你可以用其他任意的方式告知服务器。
我们下面实现一个不严格的JSONP。首先用如下命令创建新的RoR网站:
rails new ws
rails g controller Service func0
在Service控制器的func0方法中增加如下代码:
def func0
respond_to do |format|
format.js
end
end
然后在rails的app/views/service目录中添加func0.js.erb文件,内容如下:
alert("hello RoR!");
var add_elt = "<h1>hello RoR!!!";
document.write(add_elt);
注意因为我们在func0中返回的response不是一个html页面,所以正常的通过url访问func0会出错的:
//用以下url访问出错
http://127.0.0.1:3000/service/func0
下面我们建立一个本地html文件,内容如下:
<!DOCTYPE html>
<html>
<head>
<title>test JSONP fundation</title>
<script src="http://127.0.0.1:3000/service/func0?msg=hello" type="text/javascript"></script>
</head>
<body>
</body>
</html>
如果直接打开该页面会出错,因为你在服务器端没对此action关闭外联保护,在RoR中显示如下错误:
Started GET "/service/func0?msg=hello" for 127.0.0.1 at 2015-03-29 10:25:27 +0800
Processing by ServiceController#func0 as */*
Parameters: {"msg"=>"hello"}
Rendered service/func0.js.erb (0.4ms)
Security warning: an embedded <script> tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript embedding.
Completed 422 Unprocessable Entity in 9ms
ActionController::InvalidCrossOriginRequest (Security warning: an embedded <script> tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript embedding.):
我们只需要对func0 action关闭保护即可:
class ServiceController < ApplicationController
protect_from_forgery except: :func0
def func0
respond_to do |format|
format.js
end
end
end
注意config中的保护也是要关闭的:
config.action_controller.allow_forgery_protection = false
然后再次在浏览器中打开本地html文件,成功执行了web服务器中传回的js脚本,该脚本能做的事只受限于想象力而已。