Exemplo n.º 1
0
    def _rpc_process(self, req, protocol, content_type):
        """Process incoming RPC request and finalize response."""
        proto_id = protocol.rpc_info()[0]
        rpcreq = req.rpc = {'mimetype': content_type}
        try :
            self.log.debug("RPC(%s) call by '%s'", proto_id, req.authname)
            rpcreq = req.rpc = protocol.parse_rpc_request(req, content_type)
            rpcreq['mimetype'] = content_type

            # Important ! Check after parsing RPC request to add
            #             protocol-specific fields in response
            #             (e.g. JSON-RPC response `id`)
            req.perm.require('XML_RPC') # Need at least XML_RPC

            method_name = rpcreq.get('method')
            if method_name is None :
                raise ProtocolException('Missing method name')
            args = rpcreq.get('params') or []
            self.log.debug("RPC(%s) call by '%s' %s", proto_id,
                           req.authname, method_name)
            try :
                result = (XMLRPCSystem(self.env).get_method(method_name)(req, args))[0]
                if isinstance(result, GeneratorType):
                    result = list(result)
            except (TracError, PermissionError, ResourceNotFound), e:
                raise
            except Exception:
                e, tb = sys.exc_info()[-2:]
                self.log.error("RPC(%s) [%s] Exception caught while calling "
                               "%s(*%r) by %s%s", proto_id, req.remote_addr,
                               method_name, args, req.authname,
                               exception_to_unicode(e, traceback=True))
                raise ServiceException(e), None, tb
            else :
                protocol.send_rpc_result(req, result)
Exemplo n.º 2
0
        def send_rpc_result(self, req, result):
            """Send JSON-RPC response back to the caller."""
            rpcreq = req.rpc
            r_id = rpcreq.get('id')
            try:
                if rpcreq.get('method') == 'system.multicall':
                    # Custom multicall
                    args = (rpcreq.get('params') or [[]])[0]
                    mcresults = [self._json_result(
                                            isinstance(value, Exception) and \
                                                        value or value[0], \
                                            sig.get('id') or r_id) \
                                  for sig, value in izip(args, result)]

                    response = self._json_result(mcresults, r_id)
                else:
                    response = self._json_result(result, r_id)
                try:  # JSON encoding
                    self.log.debug("RPC(json) result: %s" % repr(response))
                    response = json.dumps(response, cls=TracRpcJSONEncoder)
                except Exception, e:
                    response = json.dumps(self._json_error(e, r_id=r_id),
                                          cls=TracRpcJSONEncoder)
            except Exception, e:
                self.log.error("RPC(json) error %s" %
                               exception_to_unicode(e, traceback=True))
                response = json.dumps(self._json_error(e, r_id=r_id),
                                      cls=TracRpcJSONEncoder)
Exemplo n.º 3
0
 def send_rpc_result(self, req, result):
     """Send JSON-RPC response back to the caller."""
     rpcreq = req.rpc
     r_id = rpcreq.get('id')
     try:
         if rpcreq.get('method') == 'system.multicall': 
             # Custom multicall
             args = (rpcreq.get('params') or [[]])[0]
             mcresults = [self._json_result(
                                     isinstance(value, Exception) and \
                                                 value or value[0], \
                                     sig.get('id') or r_id) \
                           for sig, value in izip(args, result)]
         
             response = self._json_result(mcresults, r_id)
         else:
             response = self._json_result(result, r_id)
         try: # JSON encoding
             self.log.debug("RPC(json) result: %s" % repr(response))
             response = json.dumps(response, cls=TracRpcJSONEncoder)
         except Exception, e:
             response = json.dumps(self._json_error(e, r_id=r_id),
                                     cls=TracRpcJSONEncoder)
     except Exception, e:
         self.log.error("RPC(json) error %s" % exception_to_unicode(e,
                                                 traceback=True))
         response = json.dumps(self._json_error(e, r_id=r_id),
                         cls=TracRpcJSONEncoder)
Exemplo n.º 4
0
        def parse_rpc_request(self, req, content_type):
            """ Parse JSON-RPC requests"""
            if not json:
                self.log.debug("RPC(json) call ignored (not available).")
                raise JsonProtocolException("Error: JSON-RPC not available.\n")

            try:
                data = json.load(req, cls=TracRpcJSONDecoder)
            except Exception, e:
                self.log.warning("RPC(json) decode error: %s",
                                 exception_to_unicode(e))
                raise JsonProtocolException(e, -32700)
Exemplo n.º 5
0
 def parse_rpc_request(self, req, content_type):
     """ Parse JSON-RPC requests"""
     if not json:
         self.log.debug("RPC(json) call ignored (not available).")
         raise JsonProtocolException("Error: JSON-RPC not available.\n")
     try:
         data = json.load(req, cls=TracRpcJSONDecoder)
         self.log.info("RPC(json) JSON-RPC request ID : %s.", data.get('id'))
         if data.get('method') == 'system.multicall':
             # Prepare for multicall
             self.log.debug("RPC(json) Multicall request %s", data)
             params = data.get('params', [])
             for signature in params :
                 signature['methodName'] = signature.get('method', '')
             data['params'] = [params]
         return data
     except Exception, e:
         # Abort with exception - no data can be read
         self.log.error("RPC(json) decode error %s", 
                           exception_to_unicode(e, traceback=True))
         raise JsonProtocolException(e, -32700)
Exemplo n.º 6
0
 def parse_rpc_request(self, req, content_type):
     """ Parse JSON-RPC requests"""
     if not json:
         self.log.debug("RPC(json) call ignored (not available).")
         raise JsonProtocolException("Error: JSON-RPC not available.\n")
     try:
         data = json.load(req, cls=TracRpcJSONDecoder)
         self.log.info("RPC(json) JSON-RPC request ID : %s.",
                       data.get('id'))
         if data.get('method') == 'system.multicall':
             # Prepare for multicall
             self.log.debug("RPC(json) Multicall request %s", data)
             params = data.get('params', [])
             for signature in params:
                 signature['methodName'] = signature.get('method', '')
             data['params'] = [params]
         return data
     except Exception, e:
         # Abort with exception - no data can be read
         self.log.error("RPC(json) decode error %s",
                        exception_to_unicode(e, traceback=True))
         raise JsonProtocolException(e, -32700)
Exemplo n.º 7
0
            except Exception:
                e, tb = sys.exc_info()[-2:]
                self.log.error(
                    "RPC(%s) [%s] Exception caught while calling "
                    "%s(*%r) by %s%s", proto_id, req.remote_addr,
                    method_name, args, req.authname,
                    exception_to_unicode(e, traceback=True))
                raise ServiceException(e), None, tb
            else:
                protocol.send_rpc_result(req, result)
        except RequestDone:
            raise
        except (TracError, PermissionError, ResourceNotFound), e:
            if type(e) is not ServiceException:
                self.log.warning("RPC(%s) [%s] %s", proto_id, req.remote_addr,
                                 exception_to_unicode(e))
            try:
                protocol.send_rpc_error(req, e)
            except RequestDone:
                raise
            except Exception, e:
                self.log.exception("RPC(%s) Unhandled protocol error",
                                   proto_id)
                self._send_unknown_error(req, e)
        except Exception, e:
            self.log.exception("RPC(%s) Unhandled protocol error", proto_id)
            self._send_unknown_error(req, e)

    def _send_unknown_error(self, req, e):
        """Last recourse if protocol cannot handle the RPC request | error"""
        method_name = req.rpc and req.rpc.get('method') or '(undefined)'
Exemplo n.º 8
0
    class JsonRpcProtocol(Component):
        r"""
        Example `POST` request using `curl` with `Content-Type` header
        and body:
 
        {{{
        user: ~ > cat body.json
        {"params": ["WikiStart"], "method": "wiki.getPage", "id": 123}
        user: ~ > curl -H "Content-Type: application/json" --data @body.json ${req.abs_href.rpc()}
        {"id": 123, "error": null, "result": "= Welcome to....
        }}}
    
        Implementation details:
    
          * JSON-RPC has no formalized type system, so a class-hint system is used
            for input and output of non-standard types:
            * `{"__jsonclass__": ["datetime", "YYYY-MM-DDTHH:MM:SS"]} => DateTime (UTC)`
            * `{"__jsonclass__": ["binary", "<base64-encoded>"]} => Binary`
          * `"id"` is optional, and any marker value received with a
            request is returned with the response.
        """

        implements(IRPCProtocol)

        # IRPCProtocol methods

        def rpc_info(self):
            return ('JSON-RPC', prepare_docs(self.__doc__))

        def rpc_match(self):
            yield ('rpc', 'application/json')
            # Legacy path - provided for backwards compatibility:
            yield ('jsonrpc', 'application/json')

        def parse_rpc_request(self, req, content_type):
            """ Parse JSON-RPC requests"""
            if not json:
                self.log.debug("RPC(json) call ignored (not available).")
                raise JsonProtocolException("Error: JSON-RPC not available.\n")

            try:
                data = json.load(req, cls=TracRpcJSONDecoder)
            except Exception, e:
                self.log.warning("RPC(json) decode error: %s",
                                 exception_to_unicode(e))
                raise JsonProtocolException(e, -32700)
            if not isinstance(data, dict):
                self.log.warning("RPC(json) decode error (not a dict)")
                raise JsonProtocolException('JSON object is not a dict',
                                            -32700)

            try:
                self.log.info("RPC(json) JSON-RPC request ID : %s.",
                              data.get('id'))
                if data.get('method') == 'system.multicall':
                    # Prepare for multicall
                    self.log.debug("RPC(json) Multicall request %s", data)
                    params = data.get('params', [])
                    for signature in params:
                        signature['methodName'] = signature.get('method', '')
                    data['params'] = [params]
                return data
            except Exception, e:
                # Abort with exception - no data can be read
                self.log.warning("RPC(json) decode error: %s",
                                 exception_to_unicode(e))
                raise JsonProtocolException(e, -32700)