pavlov99 / json-rpc Goto Github PK
View Code? Open in Web Editor NEW๐ JSON-RPC 1/2 transport implementation. Supports python 2/3 and pypy.
Home Page: http://json-rpc.readthedocs.org
License: MIT License
๐ JSON-RPC 1/2 transport implementation. Supports python 2/3 and pypy.
Home Page: http://json-rpc.readthedocs.org
License: MIT License
Can I please draw your attention to jsonrpc/manager.py
in __get_responses
where parameters are validated for a method.
Due to the way that parameters are validated, a TypeError
is raised when the method is given incorrect parameters, and thus, the following line is executed
output = response(error=JSONRPCInvalidParams()._data)
The exception handling around this doesn't account for the fact that a developer's code within that method can potentially throw a TypeError
. In this case, the real issue is hidden and the following error is returned:
{u'jsonrpc': u'2.0', u'id': 0, u'error': {u'message': u'Invalid params', u'code': -32602}}
I've just lost some time investigating why I was getting this error, and it would be great to avoid inflicting that upon someone else.
Since Dispatcher
acts as a collection, it evaluates as False
when empty. This causes the assignment self.dispatcher = dispatcher or Dispatcher()
to make a new Dispatcher
instance when passed an empty Dispatcher
.
To reproduce:
class SubDispatcher(Dispatcher):
pass
type(JSONRPCAPI(SubDispatcher()).dispatcher) == Dispatcher # This should be SubDispatcher
If application code raises a TypeError, json-rpc doesn't necessarily log the exception and stack trace. Instead, it responds with an "Invalid params" error with code "-32602".
This is also not a correct message in this case because the reason for the error is not invalid parameters sent by the caller. It is an error in application code.
I believe this issue is due to the exception handling here, where the code bypasses exception logging if the exception has type TypeError
. Or perhaps it is due to incorrect logic in is_invalid_params()
.
All should be opened in a new window.
I encountered a situation where json-rpc will break on certain exceptions. This is with json-rpc version 1.10.3 and Django 1.9.6.
If an exception is raised with code like raise Exception(foo)
, where foo
is not serializable, then json-rpc doesn't return a proper JSON response.
Here is an example stack trace:
Traceback (most recent call last):
File ".../python3.5/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File ".../python3.5/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File ".../python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File ".../python3.5/site-packages/jsonrpc/backend/django.py", line 65, in jsonrpc
response = response.json
File ".../python3.5/site-packages/jsonrpc/base.py", line 85, in json
return self.serialize(self.data)
File ".../python3.5/site-packages/jsonrpc/backend/django.py", line 62, in serialize
return json.dumps(s, cls=DatetimeDecimalEncoder)
File "/usr/lib/python3.5/json/__init__.py", line 237, in dumps
**kw).encode(obj)
File "/usr/lib/python3.5/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python3.5/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File ".../python3.5/site-packages/jsonrpc/utils.py", line 53, in default
return json.JSONEncoder.default(self, o)
File "/usr/lib/python3.5/json/encoder.py", line 180, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <Foo object> is not JSON serializable
In the case of handling an exception, it seems like json-rpc should be able to fall back to something like calling repr()
on the exception, instead of insisting that the exception be serializable.
This is because the developer doesn't necessarily have control over what exceptions are raised (e.g. if they come from third-party code, etc).
Hi!
It's a veeeeery goooood idea to add names for django's views.
Just replace this
@property
def urls(self):
urls = [
url(r'^$', self.jsonrpc),
url(r'map$', self.jsonrpc_map),
]
with this
@property
def urls(self):
urls = [
url(r'^$', self.jsonrpc, name='endpoint'),
url(r'map$', self.jsonrpc_map, name='map'),
]
in file backend/django.py
.
Let's make this library better!
Thanks ;)
Hi,
Is is possible to use the json-rpc with uart as a transporter. Do you have any example where transport layer and protocol are separated.
Thank you
the spec. mentions that "-32000 to -32099 Server error Reserved for implementation-defined server-errors."
The remainder of the space is available for application defined errors.
Could we have custom define errors for application in the future?
Like:
return JSONRPCError(-32000, "Empty Request").as_response()
or just let user define class JSONRPCEmptyRequest(JSONRPCError)
Thanks
At the moment there is no way of specifying whether a response is final or if there are more responses, meaning JSON-RPC only supports a single response for each request. This means it does not cover use-cases where the server sends response data as it comes in, rather than having to wait for all the response data to complete and then send it. Think for an example of a search engine that uses JSON-RPC.
I suggest simply adding a field called complete
which indicates whether this is the last response for the given request id.
If function does not return output, django manager returns 500 error: reference before assignment.
Function:
def echo(request=None, text=None):
send_mail(text)
default django client is used. Request:
{jsonrpc: "2.0", id: "0", method: "echo", params: {text: "My text"}}
Server response:
Traceback (most recent call last):
File "~/.env/lib/python3.4/site-packages/django/contrib/staticfiles/handlers.py", line 64, in __call__
return self.application(environ, start_response)
File "~/.env/lib/python3.4/site-packages/django/core/handlers/wsgi.py", line 187, in __call__
response = self.get_response(request)
File "~/.env/lib/python3.4/site-packages/django/core/handlers/base.py", line 199, in get_response
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
File "~/.env/lib/python3.4/site-packages/django/core/handlers/base.py", line 236, in handle_uncaught_exception
return debug.technical_500_response(request, *exc_info)
File "~/.env/lib/python3.4/site-packages/django_extensions/management/technical_response.py", line 5, in null_technical_500_response
six.reraise(exc_type, exc_value, tb)
File "~/.env/lib/python3.4/site-packages/six.py", line 659, in reraise
raise value
File "~/.env/lib/python3.4/site-packages/django/core/handlers/base.py", line 111, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "~/.env/lib/python3.4/site-packages/jsonrpc/backend/django.py", line 52, in jsonrpc
jsonrpc_request, self.dispatcher)
File "~/.env/lib/python3.4/site-packages/jsonrpc/manager.py", line 75, in handle_request
responses = [r for r in cls._get_responses(rs, dispatcher)
File "~/.env/lib/python3.4/site-packages/jsonrpc/manager.py", line 75, in <listcomp>
responses = [r for r in cls._get_responses(rs, dispatcher)
File "~/.env/lib/python3.4/site-packages/jsonrpc/manager.py", line 129, in _get_responses
yield output
UnboundLocalError: local variable 'output' referenced before assignment
Quickfix:
def echo(request=None):
send_mail()
return ""
It would be great if you could add a quick example to the readme or docstrings to show how it can be used with an http transport like Requests.
Add documentation on how to write a code, what code to write and additional changes.
nose2 is the next generation of nicer testing for Python, based on the plugins branch of unittest2.
Would this package consider supplying a client API similar to this one?
If the getaddr
tricks give people the willies, an alternative might be to explicitly initialize each remote method, for example:
from jsonrpc import Remote
# Optional kwargs for jsonrpc, headers
my_remote = Remote(url)
my_remote.add_method('echo')
my_remote.add_method('ping', notify=True)
response = my_remote.echo('foobar')
print response.result
my_remote.ping() # returns None
Hi
I want to test ur server with advanced rest client
but some param is wrong
what must I write in raw payload panel?
thanks
When my server try respone some data including bson`s objectid:
TypeError: ObjectId('5840edd2f04ba72b510184bf') is not JSON serializable
I know that should set a new JSONEncode, but how?
??
I would like to push some notifications from the server down to the client.
From the looks of it, json-rpc does not supports such use case, or does it?
Dear all,
Does this library support establishing connections to a JSON-RPC server over HTTPS?
I am currently using RPC4Django that implements a JSON-RPC interface over HTTPS (externally handled by Apache).
Thanks, Ricardo.
I want to return null as a result. I expect like {"jsonrpc": "2.0", "result": null, "id": 0}
, but it throws exceptions: ValueError: Either result or error should be used
and UnboundLocalError: local variable 'output' referenced before assignment
.
I think the reason is that it takes None
as not defined and ignores null
.
Would you correct this problem?
Example code:
from jsonrpc import JSONRPCResponseManager, dispatcher
dispatcher["nop"] = lambda: None
data = '{"jsonrpc": "2.0", "method": "nop", "params": [], "id": 0}'
JSONRPCResponseManager.handle(data, dispatcher)
This prints (python3.4):
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/json_rpc-1.8.0-py3.4.egg/jsonrpc/manager.py", line 119, in _get_responses
File "/usr/local/lib/python3.4/dist-packages/json_rpc-1.8.0-py3.4.egg/jsonrpc/manager.py", line 96, in response
File "/usr/local/lib/python3.4/dist-packages/json_rpc-1.8.0-py3.4.egg/jsonrpc/base.py", line 62, in __init__
ValueError: Either result or error should be used
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "foo.py", line 6, in <module>
JSONRPCResponseManager.handle(data, dispatcher)
File "/usr/local/lib/python3.4/dist-packages/json_rpc-1.8.0-py3.4.egg/jsonrpc/manager.py", line 58, in handle
File "/usr/local/lib/python3.4/dist-packages/json_rpc-1.8.0-py3.4.egg/jsonrpc/manager.py", line 74, in handle_request
File "/usr/local/lib/python3.4/dist-packages/json_rpc-1.8.0-py3.4.egg/jsonrpc/manager.py", line 74, in <listcomp>
File "/usr/local/lib/python3.4/dist-packages/json_rpc-1.8.0-py3.4.egg/jsonrpc/manager.py", line 122, in _get_responses
UnboundLocalError: local variable 'output' referenced before assignment
Hi pavlov99
First of all Thank You for good job done in json-rpc package!
i got exception when testing example provided on python package page for json-rpc. It concern changes in Werkzeug guess due to python v3 when request is encoded as bytes instead of string like in python v2. Managed solve it by change in manager.py (see bottom of mail)
My current setup is centos 6.5 virtual machine virtualenv and package information as below:
(app1)[root@localhost python3.3]# pip list
gevent (1.0)
greenlet (0.4.2)
hiredis (0.1.2)
json-rpc (1.1)
lxml (3.2.5)
pip (1.4.1)
redis (2.9.0)
requests (2.2.0)
setuptools (0.9.8)
tinyrpc (0.5)
uWSGI (2.0)
WebOb (1.3.1)
Werkzeug (0.9.4)
(app1)[root@localhost python3.3]# python -V
Python 3.3.3
(app1)[root@localhost python3.3]#
It can be solved by following modification to start of handle function and for backward compatibility type checking can be done on request string as below :
in manager.py
JSONRPCResponseManager.handle()
@classmethod
def handle(cls, request_str, dispatcher):
try:
if isinstance(request_str, bytes):<- modified start*************
json.loads(request_str.decode("utf-8"))
else:
json.loads(request_str) <- modified block end *****************
except (TypeError, ValueError):
return JSONRPC20Response(error=JSONRPCParseError()._data)
try:
if isinstance(request_str, bytes): <- modified start ******************
request = JSONRPCRequest.from_json(request_str.decode("utf-8"))
else:
request = JSONRPCRequest.from_json(request_str) <-- modified end *******
except JSONRPCInvalidRequestException:
return JSONRPC20Response(error=JSONRPCInvalidRequest()._data)
rs = request if isinstance(request, JSONRPC20BatchRequest) \
else [request]
responses = [r for r in cls._get_responses(rs, dispatcher)
if r is not None]
# notifications
if not responses:
return
if isinstance(request, JSONRPC20BatchRequest):
return JSONRPC20BatchResponse(*responses)
else:
return responses[0]
Currently this project uses coveralls. Tox uses https://codecov.io/gh/tox-dev/tox
I have API calls I'd like to return None from (i.e. no results returned)... however jsonrpc doesn't allow this (see line 62 at https://github.com/pavlov99/json-rpc/blob/master/jsonrpc/base.py)
File "/home/xcp/counterpartyd_build/env/lib/python3.3/site-packages/jsonrpc/manager.py", line 56, in handle
responses = [r for r in cls._get_responses(rs, dispatcher)
File "/home/xcp/counterpartyd_build/env/lib/python3.3/site-packages/jsonrpc/manager.py", line 56, in <listcomp>
responses = [r for r in cls._get_responses(rs, dispatcher)
File "/home/xcp/counterpartyd_build/env/lib/python3.3/site-packages/jsonrpc/manager.py", line 104, in _get_responses
yield response(result=result)
File "/home/xcp/counterpartyd_build/env/lib/python3.3/site-packages/jsonrpc/manager.py", line 77, in <lambda>
request.JSONRPC_VERSION](_id=request._id, **kwargs)
File "/home/xcp/counterpartyd_build/env/lib/python3.3/site-packages/jsonrpc/base.py", line 62, in __init__
raise ValueError("Either result or error should be used")
ValueError: Either result or error should be used
Could we take that line out? Any negatives to doing that?
Currently it is not possible to natively use flask blueprints subdomains wildcards, because JSONRPCAPI.jsonrpc
method in flask backend doesn't handle additional argument if blueprint subdomain is defined as a wildcard, i.e.
app.register_blueprint(api.as_blueprint(), subdomain='<subdomain>')
In this way, the api can be used through api.example.com
or api2.example.com
or other.example.com
.
Expected behavior: api can be used through registered endpoint and subdomain wildcard is available in the jsonrpc method.
Actual behavior: jsonrpc
raises an exception, that it can't accept additional argument, i.e. subdomain
.
Reproduces how often: always
nginx 1.10.3
or /etc/hosts
json-rpc 1.10.8
I can see there are multiple ways this can be solved. For now I am using a workaround to handle subdomains in the application, which involves nginx and setting some headers.
I would also like to contribute and make this possible, what are your thoughts on this feature?
If I use a class to hold the dispatcher methods and decorate them with @dispatcher.add_method
I always get "Invalid params" code: -32602.
I have to add a parameter 'self':None to the request to get this to work.
Thank you
run.py
from flask import Flask
from jsonrpc.backend.flask import api
app = Flask(__name__)
app.register_blueprint(api.as_blueprint())
app.add_url_rule('/', 'api', api.as_view())
@api.dispatcher.add_method
def my_method(*args, **kwargs):
return args, kwargs
if __name__ == '__main__':
app.run(debug=True)
then i use postman to post the url : localhost:5000/api/
data:{
"jsonrpc": "2.0",
"id": "1111",
"method": "my_method",
"params": ["1"]
}
response 404
help~
I receive a JSON string and want to construct a JSONRPC20Response
object, like:
JSONRPC20Response.from_json(my_str)
or JSONRPC20Response(**json.loads(my_str))
However, JSONRPC20Response
expects _id
instead of id
, so the response's id
is always None
.
I realize I could simply do JSONRPC20Response(_id=obj.get('id'), ...)
but it seems like there should be a more natural way. I would expect the object representation of a response to be easily constructed from a JSON response. Maybe I'm missing something?
classes are about the same. Otherwise protocol is meaningless.
Please, add Python 3.5, Python 3.6, Django 1.11 and Django 2.0b1 (allow failures) support for tests...
Hi
I want to make a simple chat server with this api but it is staighless how can I send a interrupt to the client for fetching messages?
if I use "always check" data, it become harmful for the server
any ideas?
Unexpectedly occurs. Seems pretty clear.
Version: json-rpc==1.9.0
File "/app_path/.env/local/lib/python2.7/site-packages/jsonrpc/manager.py", line 59, in handle
return cls.handle_request(request, dispatcher)
File "/app_path/.env/local/lib/python2.7/site-packages/jsonrpc/manager.py", line 75, in handle_request
responses = [r for r in cls._get_responses(rs, dispatcher)
File "/app_path/.env/local/lib/python2.7/site-packages/jsonrpc/manager.py", line 129, in _get_responses
yield output
UnboundLocalError: local variable 'output' referenced before assignment
field with data should be changed to avoid misunderstanding with batchrequest._dict (it is list)
I need to pass some additional data to the request dispatcher (a connection ID)
What is the best way to accomplish this? Currently I'm munging the request like so:
def munge_request(request, client_id):
try:
if isinstance(request, bytes):
decoded = request.decode("utf-8")
parsed = json.loads(decoded)
if 'params' in parsed:
parsed["params"] = {"orig_params": parsed["params"], "client_id": client_id}
return json.dumps(parsed)
except Exception as e:
log.error("Munge_request caught exception! %s" % e)
return request
This is obviously not optimal for multiple reasons. Is there a better way?
Hi
I couldn't find anything about this in the docs:
Does this library support a variable number of args and kwargs for a handler function?
Example:
@dispatcher.add_method
def foobar(*args, **kwargs):
return kwargs["foo"] + kwargs["bar"] + args[0]
library is done, there 3 places for six, possible to exclude dependency
The pypi source archive isn't including the LICENSE.txt
file. Would it be possible to add it? It is very helpful when packaging this for Linux distributions. Thank you.
The link at https://pypi.org/project/json-rpc/#competitors is no longer useful since the list of implementations is gone from the Wikipedia article https://en.wikipedia.org/wiki/JSON-RPC
We are dealing with a client library that sends "params": null
in a JSON-RPC 1.0 "hello" request, which is rejected by JSONRPC10Request.from_json()
(as specifically tested by TestJSONRPC10Request.test_params_validation_none()
) because it's not a list.
The JSON-RPC 2.0 Specification states the following:
If present, parameters for the rpc call MUST be provided as a Structured value. Either by-position through an Array or by-name through an Object.
but the JSON-RPC 1.0 Specification just says
params - An Array of objects to pass as arguments to the method
which makes it pretty clear that an empty array is what's expected if you want to pass zero params, but isn't totally definitive on whether null
/None
is a valid value.
Would it cause any problems to treat null
as if it's an empty list for JSON-RPC 1.0?
The implementation might look like:
# JSONRPC10Request
@params.setter
def params(self, value):
value = value if value is not None else [] # <= New line
if not isinstance(value, (list, tuple)):
raise ValueError("Incorrect params {0}".format(value))
self._data["params"] = list(value)
At the moment it fails.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.