Проблема с RPC Trac JSON - Использование jQuery AJAX с PHP-прокси


Хорошо, это сложный вопрос, но я думаю, что здесь мне не хватает чего-то действительно простого.

Цель

Я пытаюсь создать интерфейс для Trac из другого домена, используя XMLRPCPLUGINJSON-интерфейс Trac API. Я использую скрипт на стороне сервера PHP в качестве прокси-сервера из-за политики Javascript того же происхождения.


Статус

Прокси-сервер, похоже, (в основном) работает, потому что я действительно получаю ответ из Trac в интерфейсе, управляемом jQuery. Однако я всегда получите такой ответ:

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

Вот две записи в моем журнале отслеживания, которые соответствуют каждому запросу:

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
  • Питон: Python 2.6
  • Веб-сервер: Apache 2.2.14
  • ОС: Ubuntu 10.04

Что я делаю не так?

Author: Andrew Ensley, 2012-03-05

2 answers

Существует хорошая библиотека Trac JSON-RPC для PHP, которая помогает вам создавать правильные запросы.

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

 1
Author: Gregor, 2012-03-05 18:23:30

Понял это.

Проблема заключалась в content параметре в $cparams.

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"
    )
);

Исправил это.

 1
Author: Andrew Ensley, 2012-03-05 19:39:30