Search code examples
jquerytracjson-rpc

Trac JSON RPC Issue when using JQuery AJAX


I'm trying to access some data through JSON RPC using the trac XMLRPCPlugin using my own method 'plugged' into one of it's extension points on the server side and a JQuery AJAX request on the client side. I can access the data fine using the Firefox poster extension however using the JQuery ajax request gives an error message. The error message I get is:

Trac[web_ui] DEBUG: RPC incoming request of content type 'application/json' dispatched 
to <tracrpc.json_rpc.JsonRpcProtocol object at 0x03CA51F0>
Trac[web_ui] DEBUG: RPC(JSON-RPC) call by 'PaulWilding'
Trac[json_rpc] ERROR: RPC(json) decode error 
Traceback (most recent call last):
  File "build\bdist.win32\egg\tracrpc\json_rpc.py", line 148, in parse_rpc_request
    data = json.load(req, cls=TracRpcJSONDecoder)
  File "C:\Python27\Lib\json\__init__.py", line 278, in load
    **kw)
  File "C:\Python27\Lib\json\__init__.py", line 339, in loads
    return cls(encoding=encoding, **kw).decode(s)
  File "build\bdist.win32\egg\tracrpc\json_rpc.py", line 99, in decode
    obj = json.JSONDecoder.decode(self, obj, *args, **kwargs)
  File "C:\Python27\Lib\json\decoder.py", line 366, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\Python27\Lib\json\decoder.py", line 384, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded
Trac[web_ui] ERROR: RPC(JSON-RPC) Error
Traceback (most recent call last):
  File "build\bdist.win32\egg\tracrpc\web_ui.py", line 143, in _rpc_process
    rpcreq = req.rpc = protocol.parse_rpc_request(req, content_type)
  File "build\bdist.win32\egg\tracrpc\json_rpc.py", line 162, in parse_rpc_request
    raise JsonProtocolException(e, -32700)
JsonProtocolException: No JSON object could be decoded
Trac[json_rpc] DEBUG: RPC(json) encoded response: {"error": {"message": "JsonProtocolException details : No JSON object could be decoded", "code": -32700, "name": "JSONRPCError"}, "result": null, "id": null}

The JQuery request is:

 url: "http://localhost/Projects/jsonrpc",
   contentType: "application/json",
   dataType: "jsonp",
   data: {"method": "breq.getBreqs"},
   type: 'POST',
   success: function (repsonse) {
          alert("success");
   },
   error: function (jqXHR, textStatus, errorThrown) {
          alert("Error: " + textStatus);
   }      

The request I’ve got working through Poster is simply “{"method": "breq.getBreqs"}” with content set to application/json and the URL the same as above.

I’ve read a few posts about this problem when used with a PHP proxy and tried logging the request in the parse_rpc_request in the trac rpc plugin but this only returned the same string of “” for both the working and non-working requests.

I don't think this is a problem due to Javascript's Same Origin Policy as the request is to my trac testbed which is on my machine. However, once the plugin is deployed onto a server still inside the main network will this become an issue and if so, how should I deal with it?

If the problem isn't to do with the Same Origin Policy does anyone know what is causing it?


Solution

  • Your call will URL encode the input, which is not what you want for JSON-RPC. You want the request body to be a JSON string with no added characters or information.

    Here is a new version of your snippet that loads fine from a browser javascript console, but note that my example calls system.listMethods (and not your custom method) so that it works for any Trac RPC installation:

    $.ajax({
       url: "http://localhost/trac/rpc",
       contentType: "application/json",
       dataType: "text",
       data: JSON.stringify({method: "system.listMethods", id: 42}),
       type: 'POST',
       success: function (response) {
           incoming = JSON.parse(response)
           alert("Result ID " + incoming["id"] + ": " + incoming["result"]);
       },
       error: function (jqXHR, textStatus, errorThrown) {
           alert("Error: " + textStatus);
       }
    });
    

    Use /login/rpc URL unless anonymous have assigned XML_RPC permission.