Example #1
0
async def server_handle(websocket, path):
    request = await websocket.recv()

    json_request = json.loads(request)
    if isinstance(json_request, list):
        if any(i["method"] == "test_cancel" for i in json_request):
            got_cancel.set_result(True)
            response = BatchResponse()
            for i in json_request:
                response.append(RequestResponse(i["id"], ["CANCELLED"]))
        elif any(i["method"] == "test_progress" for i in json_request):
            response = BatchResponse()
            for i in json_request:
                progress_notification = rockets.Request(
                    "progress",
                    {"amount": 0.5, "operation": "almost done", "id": i["id"]},
                )
                await websocket.send(progress_notification.json)
                response.append(RequestResponse(i["id"], "DONE"))
        else:
            response = await methods.dispatch(request)
    else:
        response = await methods.dispatch(request)
    if not response.is_notification:
        await websocket.send(str(response))
Example #2
0
async def server_handle(websocket, path):
    request = await websocket.recv()

    json_request = json.loads(request)
    if isinstance(json_request, list):
        if any(i['method'] == 'test_cancel' for i in json_request):
            got_cancel.set_result(True)
            response = BatchResponse()
            for i in json_request:
                response.append(RequestResponse(i['id'], ['CANCELLED']))
        elif any(i['method'] == 'test_progress' for i in json_request):
            response = BatchResponse()
            for i in json_request:
                progress_notification = rockets.Request(
                    'progress', {
                        'amount': 0.5,
                        'operation': 'almost done',
                        'id': i['id']
                    })
                await websocket.send(progress_notification.json)
                response.append(RequestResponse(i['id'], 'DONE'))
        else:
            response = await methods.dispatch(request)
    else:
        response = await methods.dispatch(request)
    if not response.is_notification:
        await websocket.send(str(response))
Example #3
0
 def test(self):
     response = RequestResponse(1, 'foo')
     self.assertEqual({
         'jsonrpc': '2.0',
         'result': 'foo',
         'id': 1
     }, response)
Example #4
0
 def test(self):
     response = RequestResponse(1, "foo")
     self.assertEqual({
         "jsonrpc": "2.0",
         "result": "foo",
         "id": 1
     }, response)
Example #5
0
async def server_handle(websocket, path):
    request = await websocket.recv()

    json_request = json.loads(request)
    method = json_request['method']
    if method == 'test_progress':
        progress_notification = rockets.Request('progress', {
            'amount': 0.5,
            'operation': 'almost done',
            'id': json_request['id']
        })
        await websocket.send(progress_notification.json)
        response = RequestResponse(json_request['id'], 'DONE')
    elif method == 'test_cancel':
        await websocket.recv()
        response = RequestResponse(json_request['id'], 'CANCELLED')
    else:
        response = await methods.dispatch(request)
    if not response.is_notification:
        await websocket.send(str(response))
Example #6
0
async def server_handle(websocket, path):
    request = await websocket.recv()

    json_request = json.loads(request)
    method = json_request["method"]
    if method == "test_progress":
        progress_notification = rockets.Request(
            "progress",
            {
                "amount": 0.5,
                "operation": "almost done",
                "id": json_request["id"]
            },
        )
        await websocket.send(progress_notification.json)
        response = RequestResponse(json_request["id"], "DONE")
    elif method == "test_cancel":
        await websocket.recv()
        response = RequestResponse(json_request["id"], "CANCELLED")
    else:
        response = await methods.dispatch(request)
    if not response.is_notification:
        await websocket.send(str(response))
Example #7
0
 def process(self, methods):
     """Calls the method and returns a Response object."""
     error = None
     try:
         result = _call(methods, self.method_name, self.args, self.kwargs)
     # Catch any JsonRpcServerError raised (Invalid Request, etc)
     except JsonRpcServerError as e:
         error = e
     # Catch uncaught exceptions and respond with ServerError
     except Exception as e:  # pylint: disable=broad-except
         # Log the uncaught exception
         logger.exception(e)
         error = e  # pylint: disable=redefined-variable-type
     if error:
         if self.is_notification and not self.notification_errors:
             return NotificationResponse()
         else:
             return ExceptionResponse(error, self.request_id)
     # Success
     if self.is_notification:
         return NotificationResponse()
     else:
         return RequestResponse(self.request_id, result)
Example #8
0
 def test_str(self):
     response = RequestResponse(1, 'foo')
     self.assertEqual('{"jsonrpc": "2.0", "result": "foo", "id": 1}',
                      str(response))
Example #9
0
 def test_no_result(self):
     # Perfectly fine.
     response = RequestResponse(1, None)
     self.assertEqual({'jsonrpc': '2.0', 'result': None, 'id': 1}, response)
Example #10
0
 def test_no_id(self):
     # Not OK - requests must have an id.
     with self.assertRaises(ValueError):
         RequestResponse(None, 'foo')
Example #11
0
 def test_no_result(self):
     # Perfectly fine.
     response = RequestResponse(1, None)
     self.assertEqual({"jsonrpc": "2.0", "result": None, "id": 1}, response)
def dispatch(methods, request, notification_errors=False):
    """Dispatch JSON-RPC requests to a list of methods::

        r = dispatch([cat], {'jsonrpc': '2.0', 'method': 'cat', 'id': 1})

    The first parameter can be either:

    - A *list* of functions, each identifiable by its ``__name__`` attribute.
    - Or a *dictionary* of name:method pairs.

    When using a **list**, the methods must be identifiable by a ``__name__``
    attribute.

    Functions already have a ``__name__`` attribute::

        >>> def cat():
        ...     return 'meow'
        ...
        >>> cat.__name__
        'cat'
        >>> dispatch([cat], ...)

    Lambdas require setting it::

        >>> cat = lambda: 'meow'
        >>> cat.__name__ = 'cat'
        >>> dispatch([cat], ...)

    As do partials::

        >>> max_ten = partial(min, 10)
        >>> max_ten.__name__ = 'max_ten'
        >>> dispatch([max_ten], ...)

    Alternatively, consider using a **dictionary** instead::

        >>> dispatch({'cat': cat, 'max_ten': max_ten}, ...)

    See the `Methods`_ module for another easy way to build the list of methods.

    :param methods: List or dict of methods to dispatch to.
    :param request:
        JSON-RPC request. This can be in dict or string form.  Byte arrays
        should be `decoded
        <https://docs.python.org/3/library/codecs.html#codecs.decode>`_ first.
    :param notification_errors:
        Should `notifications
        <http://www.jsonrpc.org/specification#notification>`_ get error
        responses? Typically notifications don't receive any response, except
        for "Parse error" and "Invalid request" errors. Enabling this will
        include all other errors such as "Method not found". A notification is
        then similar to many unix commands - *"There was no response, so I can
        assume the request was successful."*
    :returns: A `Response`_ object - either `RequestResponse`_,
              `NotificationResponse`_, or `ErrorResponse`_ if there was a
              problem processing the request. In any case, the return value
              gives you ``body``, ``body_debug``, ``json``, ``json_debug``, and
              ``http_status`` values.
    """

    # Process the request
    r = None
    error = None
    try:
        # Log the request
        request_log.info(str(request))
        # Create request object (also validates the request)
        r = Request(request)
        # Call the requested method
        result = _call(methods, r.method_name, r.args, r.kwargs)
    # Catch any JsonRpcServerError raised (Invalid Request, etc)
    except JsonRpcServerError as e:
        error = e
    # Catch uncaught exceptions, respond with ServerError
    except Exception as e:  # pylint: disable=broad-except
        # Log the uncaught exception
        logger.exception(e)
        # Create an exception object, used to build the response
        error = ServerError(str(e))

    # Now build a response.
    # Error
    if error:
        # Notifications get a non-response - see spec
        if r and r.is_notification and not notification_errors:
            response = NotificationResponse()
        else:
            # Get the 'id' part of the request, to include in error response
            request_id = r.request_id if r else None
            response = ErrorResponse(error.http_status, request_id, error.code,
                                     error.message, error.data)
    # Success
    else:
        # Notifications get a non-response
        if r and r.is_notification:
            response = NotificationResponse()
        else:
            response = RequestResponse(r.request_id, result)

    # Log the response and return it
    response_log.info(response.body,
                      extra={
                          'http_code': response.http_status,
                          'http_reason':
                          HTTP_STATUS_CODES[response.http_status]
                      })
    return response