Trac JSON RPC 问题 - 将 jQuery AJAX 与 PHP 代理一起使用

Posted

技术标签:

【中文标题】Trac JSON RPC 问题 - 将 jQuery AJAX 与 PHP 代理一起使用【英文标题】:Trac JSON RPC Issue - Using jQuery AJAX with PHP proxy 【发布时间】:2012-03-05 17:24:03 【问题描述】:

好吧,这是一个棘手的问题,但我想我在这里遗漏了一些非常简单的东西。

目标

我正在尝试使用XmlRpcPlugin 到Trac API 的JSON 接口从另一个域创建到Trac 的接口。由于 javascript 的 Same Origin Policy,我使用 php 服务器端脚本作为代理。


状态

代理似乎(大部分)工作,因为我确实在 jQuery 驱动的界面中从 Trac 收到了响应。但是,我总是收到这样的回复:


  "error": 
    "message": "JsonProtocolException details : No JSON object could be decoded",
    "code": -32700,
    "name": "JSONRPCError"
  ,
  "result": null,
  "id": null

这些是我的 Trac 日志中与每个请求对应的两个条目:

2012-03-05 11:37:55,943 Trac[json_rpc] ERROR: RPC(json) decode error
Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/TracXMLRPC-1.1.2_r11148-py2.6.egg/tracrpc/json_rpc.py", line 148, in parse_rpc_request
    data = json.load(req, cls=TracRpcJSONDecoder)
  File "/usr/lib/python2.6/json/__init__.py", line 267, in load
    parse_constant=parse_constant, **kw)
  File "/usr/lib/python2.6/json/__init__.py", line 318, in loads
    return cls(encoding=encoding, **kw).decode(s)
  File "/usr/local/lib/python2.6/dist-packages/TracXMLRPC-1.1.2_r11148-py2.6.egg/tracrpc/json_rpc.py", line 99, in decode
    obj = json.JSONDecoder.decode(self, obj, *args, **kwargs)
  File "/usr/lib/python2.6/json/decoder.py", line 319, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.6/json/decoder.py", line 338, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

2012-03-05 11:37:55,943 Trac[web_ui] ERROR: RPC(JSON-RPC) Error
Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/TracXMLRPC-1.1.2_r11148-py2.6.egg/tracrpc/web_ui.py", line 143, in _rpc_process
    rpcreq = req.rpc = protocol.parse_rpc_request(req, content_type)
  File "/usr/local/lib/python2.6/dist-packages/TracXMLRPC-1.1.2_r11148-py2.6.egg/tracrpc/json_rpc.py", line 162, in parse_rpc_request
    raise JsonProtocolException(e, -32700)
JsonProtocolException: No JSON object could be decoded

代码

我的 jQuery 代码:

$.ajax(
    url: "/ajax/trac_proxy.php",
    dataType: "json",
    data: "method": "system.listMethods", "id": 1,
    timeout: 5000,
    type: 'POST',
    success: function(data, status, XHR)
        alert(JSON.stringify(data));
    
);

我的 PHP 脚本(/ajax/trac_proxy.php - 为清楚起见已缩短):

<?php
    $cparams = array(
        'http' => array(
            'method' => 'POST',
            'ignore_errors' => true,
            'content' => http_build_query($_POST),
            'header' => "Authorization: Basic " . base64_encode($username . ':' . $password) . "\r\n"
                      . "Content-Type: application/json\r\n"
        )
    );
    $context = stream_context_create($cparams);
    $fp = fopen('https://mytracdomain.com/login/jsonrpc', 'rb', false, $context);
    echo stream_get_contents($fp);
?>

调试结果

要查看 PHP 正在做什么/做什么,我将 /ajax/trac_proxy.php 更改为:

$cparams = array(
    'http' => array(
        'content' => http_build_query($_POST),
        'method' => 'POST',
        'ignore_errors' => true,
        'header' => "Authorization: Basic " . base64_encode($username . ':' . $password) . "\r\n"
                  . "Content-Type: application/json\r\n"
    )
);

var_dump($_POST);
var_dump(http_build_query($_POST));
var_dump($cparams);

这是我回来的:

array(2) 
  ["method"]=>
  string(18) "system.listMethods"
  ["id"]=>
  string(1) "1"


string(30) "method=system.listMethods&id=1"

array(1) 
  ["http"]=>
  array(4) 
    ["content"]=>
    string(30) "method=system.listMethods&id=1"
    ["method"]=>
    string(4) "POST"
    ["ignore_errors"]=>
    bool(true)
    ["header"]=>
    string(79) "Authorization: Basic <REMOVED>
Content-Type: application/json
"
  


环境

追踪Trac 0.11.7 PythonPython 2.6 网络服务器Apache 2.2.14 操作系统Ubuntu 10.04

我做错了什么?

【问题讨论】:

你能在 PHP 中使用 echo 查看 http_build_query($_POST) 的内容吗? /跨度> @Gregor:我已将该信息添加到“调试结果”下的问题中。 请看看我的答案,其中包含一个不错的 Trac JSON-RPC 库 - 希望这会有所帮助! 【参考方案1】:

有一个不错的用于 PHP 的 Trac JSON-RPC 库,可以帮助您构建正确的请求。

https://github.com/bgreenacre/TRAC-JSON-RPC-PHP-class

【讨论】:

感谢您的链接。现在就试一试。 糟糕,该代码依赖于 CURL。我无法在我的环境中启用它。 我自己想出来的。问题是内容的编码。在这里查看我的答案:***.com/a/9572818/20801 尽管您的回答对我不起作用,但您的 cmets 和问题帮助我解决了这个问题。谢谢!【参考方案2】:

想通了。

问题在于$cparams 中的content 参数。

http_build_query() 返回一个 URL 查询字符串。 JSON-RPC 插件期待的是一个 JSON 字符串(想象一下),json_encode() 很容易提供。

改变这个:

$cparams = array(
    'http' => array(
        'content' => http_build_query($_POST),
        'method' => 'POST',
        'ignore_errors' => true,
        'header' => "Authorization: Basic " . base64_encode($username . ':' . $password) . "\r\n"
                  . "Content-Type: application/json\r\n"
    )
);

到这里:

$cparams = array(
    'http' => array(
        'content' => json_encode($_POST),
        'method' => 'POST',
        'ignore_errors' => true,
        'header' => "Authorization: Basic " . base64_encode($username . ':' . $password) . "\r\n"
                  . "Content-Type: application/json\r\n"
    )
);

修复它。

【讨论】:

以上是关于Trac JSON RPC 问题 - 将 jQuery AJAX 与 PHP 代理一起使用的主要内容,如果未能解决你的问题,请参考以下文章

使用 JQuery AJAX 时跟踪 JSON RPC 问题

Trac XML-RPC Plugin:票数

可以将 Jersey-Json/Jackson 配置为生成 json-rpc-1.0 吗?

将正确的 JSON 作为参数发送到 RPC

我可以使用 JSON-RPC 将文件发布到网络服务吗?

无法通过 JSON-RPC 将 GETBLOCKHASH 发布到比特币核心