最近遇到相似的问题,可以参考下。备份下。
========================================================
这两天用Ajax连接后端JSON-RPC的服务, 后端的service是用C++写的,用到的是cppcms,作者给的例子是python写的,需要设置Content-Type:application/json,经测试,python可以正常访问到这个service。
后端由于已经限定了Content-Type, 考虑到需要和其他服务器端通信也需要到这个设置,不好做出修改。所以在浏览器端也要进行该设置,在查阅了资料后,发现请求头的类型可以自己任意设置,例如 setRequestHeader(name,value);
新建了一个本地的html测试后,设置了xhr.setRequestHeader("Content-Type","application/json");
测试的结果是ie8 能够正常设置Content-Type,能够和后端交互,服务器端返回status200, 获得正确结果。
但是chrome里和ff里反复设置content-type,都不成功,在浏览器的网络面板里也没看到发出去的请求。用fiddler等工具也没有发现正确的请求头部和正确的应答结果。
在chrome里只有设置了xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded,application/json; charset=utf-8");才能在网络面板里看到,但是被浏览器给canceled掉了.
而且Content-Type中在第二个设置了application/json也不能通过,从这个可以发现,application/json; 必须要设置为第一个参数。
调了很长都未果,后来用firebug的rest插件模拟一个请求,设置content-type:application/json, 参数"{'method':'sum','params':[1,2],'id':1}",得到正确的结果3,考虑到这些发现了是一个跨域的情况,解决了同源策略问题后,得到了正确的结果,Content-Type也正确的设置上了。
开始时由于没有正确的设置上Content-Type,思路限定在Content-Type值的设置方法上了,例如HTTP请求一些设置依赖关系,例如是否要同时设置上Accept,Content-length等。 最后才发现是同源策略影响到了setRequestHeader正确的设置。
简单说一下JSON-RPC
JSON-RPC分为1.0 和2.0
1.0的参数设置 可以参考http://json-rpc.org/wiki/specification
- · method - AString containing the name of the method to be invoked.
- · params - AnArray of objects to pass as arguments to the method.
- · id - The request id. This can be of anytype. It is used to match the response with the request that it is replying to.
method:是请求的方法名
params:是一个参数数组
id:是一个唯一的id
一个例子是"{'method':'sum','params':[1,2],'id':1}";
2.0多加了一个版本号 参考 http://groups.google.com/group/json-rpc/web/json-rpc-1-2-proposal
{"jsonrpc": "2.0", "method":"subtract", "params": [42, 23], "id": 1}
在项目中用到的是1.0的格式
测试代码如下:
var xhr = new XMLHttpRequest();
var params = "{'method':'sum','params':[1,2],'id':1}";
xhr.open("post", “path /rpc”, true);
xhr.setRequestHeader("Content-Type","application/json"); //要再open方法后调用
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 &&xhr.status < 300 || xhr.status === 304) {
alert("ok")
}
}
}
xhr.send(params);
如果用jquery调用更简单
$.ajax({
url: “/rpc",
type: "post",
dataType: "json",
data: '{"method":"sum","params":[1,2],"id":1}',
contentType: "application/json; charset=utf-8",
beforeSend: function(x) {
//这个不需要设置,要不可能在有得浏览器中出现重复的content-type
//x.setRequestHeader("Content-Type", "application/json;charset=utf-8");
},
success: function(json) {
alert("ok");
},
error: function(x, e) {
alert("error");
},
complete: function(x) {
alert("complete");
}
});