cenobites / flask-jsonrpc Goto Github PK
View Code? Open in Web Editor NEWBasic JSON-RPC implementation for your Flask-powered sites
License: Other
Basic JSON-RPC implementation for your Flask-powered sites
License: Other
Work
@jsonrpc.method('add(a=int, b=int)')
def add(a, b)->int:
...
And work
@jsonrpc.method('add(a=int, b=int)')
def add(a: int, b: int):
...
And work
@jsonrpc.method('add(a=int, b=int)')
def add(a: int, b: int)->int:
...
Add parameter validate to init for compatibility
from flask_jsonrpc import JSONRPC
jsonrpc = JSONRPC(app, '/api', validate=False)
Hello,
do you know any issue involving use of flask-jsonrpc with gevent ?
I've realized an API that use Blueprint, following your modular example.
In normal way (http) it works correctly.
Using WSGIServer (https) I've always get exception MethodNotFoundError.
app = Flask(__name__)
jsonrpc = JSONRPC(app, '/api', enable_web_browsable_api=True)
http_server = WSGIServer((Config.host, Config.port), app,
keyfile=Config.app_path + "\privkey.pem",
certfile=Config.app_path + "\cacert.pem")
I try to put jsonrpc instead of app in the call of WSGIServer, but it doesn't work, I get back TypeError: 'JSONRPC' object is not callable.
Can you help me ?
Thanks in advice, best regards
Giuseppe Garzotto
how to provide 'Access-Control-Allow-Origin' header automatically?
i'm try to use this decorator http://flask.pocoo.org/snippets/56/ but no.
@crossdomain(origin='*', methods=['GET', 'OPTIONS', 'POST'])
@jsonrpc.method('addSession')
def addSession(params):
...
pip install --upgrade flask-JSONRPC
Version 0.1 is installed by this command. Version 0.2 does not appear in pypi although its documentation is updated to 0.2 on its pypi page.
$ pip install flask-JSONRPC==0.2 Could not find a version that satisfies the requirement flask-JSONRPC==0.2
_site_api always uses default_site, so you can't define separate JSONRPCSites for different JSONRPC instances, which means you can't use different URL paths accepting JSON queries with same method names (which may be very useful in REST apps handling many similar clients).
However, this issue is easy to fix - all you need is wrap "_site_api" to "View" class, define "dispatch_request" method which accepts "site" as param, and rewrite "add_url_rule"s, (use unique "endpoints" and pass self.site to View constructor).
I can provide this patch, but my version (installed from pip) differs from master branch.
Before I go off and try to implement this, do you think it's possible?
If the bound function has defaulted arguments, maybe fill in the web UI with the default value (if possible to retrieve), or just mark it as non-required to hit the 'send' button.
Example:
jsonrpc = JSONRPC(app, '/api', enable_web_browsable_api=True)
@jsonrpc.method('foo(int)->bool')
def foo(x=100):
return True;
Thanks! If you cannot implement this but think it's possible, I think I can tackle it!
It looks like the API used by Flask-JsonRPC to inspect functions (as of version 0.3.1) is not compatible with typing annotations...
Example:
@jsonrpc.method('Test.Ping')
def ping() -> str:
return 'pong'
causes the following exception:
Traceback (most recent call last):
File "./test.py", line 17, in <module>
class Server:
File "./test.py", line 29, in Server
def ping() -> str:
File "/home/abustany/test/.direnv/python-3.7.1/lib/python3.7/site-packages/flask_jsonrpc/__init__.py", line 225, in decorator
arg_names = getargspec(f)[0]
File "/usr/lib64/python3.7/inspect.py", line 1080, in getargspec
raise ValueError("Function has keyword-only parameters or annotations"
ValueError: Function has keyword-only parameters or annotations, use getfullargspec() API which can support them
Hi, HTTP 500 error occurred when calling rpc in browsable webconsole:
Traceback (most recent call last)
File "C:\Python27\lib\site-packages\flask-0.10-py2.7.egg\flask\app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Python27\lib\site-packages\flask-0.10-py2.7.egg\flask\app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "C:\Python27\lib\site-packages\flask-0.10-py2.7.egg\flask\app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\Python27\lib\site-packages\flask-0.10-py2.7.egg\flask\app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "C:\Python27\lib\site-packages\flask-0.10-py2.7.egg\flask\app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Python27\lib\site-packages\flask-0.10-py2.7.egg\flask\app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Python27\lib\site-packages\flask-0.10-py2.7.egg\flask\app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Python27\lib\site-packages\flask-0.10-py2.7.egg\flask\app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Python27\lib\site-packages\flask_jsonrpc-0.2-py2.7.egg\flask_jsonrpc\__init__.py", line 158, in wrapper
response_dict, status_code = site.dispatch(request, method)
File "C:\Python27\lib\site-packages\flask_jsonrpc-0.2-py2.7.egg\flask_jsonrpc\site.py", line 267, in dispatch
raw_data = extract_raw_data_request(request)
File "C:\Python27\lib\site-packages\flask_jsonrpc-0.2-py2.7.egg\flask_jsonrpc\helpers.py", line 56, in extract_raw_data_request
raw_data = _extract_raw_data_request(request)
File "C:\Python27\lib\site-packages\flask_jsonrpc-0.2-py2.7.egg\flask_jsonrpc\helpers.py", line 52, in _extract_raw_data_request
return u(request.data)
File "C:\Python27\lib\site-packages\flask_jsonrpc-0.2-py2.7.egg\flask_jsonrpc\_compat.py", line 85, in u
return unicode(s)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 64: ordinal not in range(128)
This problem doesn't exist when using version 787fb55 (2013/11/21). There's Chinese character in posted JSON(utf-8 encoded).
This is currently marked as a TODO. An optional keyword arg to the JSONRPC constructor could allow a class or function to used to provide application specific argument injection.
Currently ServiceProxy() uses urllib, which in Python 2.x doesn't allow for HTTP header modification. This becomes an issue when trying to send JSON strings with characters that contain values that look like url-encoded characters. By default urllib sends POST data with the HTTP header "Content-Type" set to "application/x-www-form-urlencoded". The JSON client should be using "application/json" for the "Content-Type" in the HTTP header. The following code is meant to demonstrate the problem:
Server:
from flask import Flask
from flask_jsonrpc import JSONRPC
app = Flask("DEBUG")
annote = JSONRPC(app,'/DEBUG',enable_web_browsable_api=True)
@annote.method('one(str)->str')
def one(instr):
print("string is %s" % instr)
return instr
app.run(host='0.0.0.0',port=5001,debug=True)
Client:
from flask_jsonrpc.proxy import ServiceProxy
s=ServiceProxy('http://0.0.0.0:5001/DEBUG')
print(s.one('No%20Space'))
Resulting output:
{u'jsonrpc': u'2.0', u'id': u'df4932b0-8551-11e4-86b1-0026b9641702', u'result': u'No Space '}
The "%20" was decoded into a space (" ").
The solution for this would be to replace urllib with urllib2 in _compat.py and subsequently the import of urllib in ServiceProxy(). The default HTTP header "Content-Type" should be set to "application/json" but there will be a overriding parameter available so users can provide their own HTTP headers dictionary.
The following are code snippets that illustrate the solution:
_compat.py:
For PY3:
encode_filename = _identity
get_next = lambda x: x.__next__
from urllib.parse import urlparse
from urllib.request import urlopen
from urllib.request import Request
For PY2:
return filename
from urlparse import urlparse
from urllib2 import urlopen
from urllib2 import Request
proxy.py:
class ServiceProxy(object):
DEFAULT_HEADERS = {"Content-Type":"application/json"}
def __init__(self, service_url, service_name=None, version='2.0', headers=None):
self.headers = headers or self.DEFAULT_HEADERS
self.version = text_type(version)
...
...
...
def send_payload(self, params):
"""Performs the actual sending action and returns the result
"""
data = json.dumps({
'jsonrpc': self.version,
'method': self.service_name,
'params': params,
'id': text_type(uuid.uuid1())
})
data_binary = data.encode('utf-8')
url_request = Request(self.service_url,data_binary,headers=self.headers)
return urlopen(url_request).read()
Thanks for taking a look!
Some errors cause response objects that violate the JSON RPC 2.0 spec, because they have both, a "result" and "error" member set. An example would be MethodNotFoundError.
See https://github.com/cenobites/flask-jsonrpc/blob/723db17b1ef11d15d4180fd0e372b9a51723f4e4/flask_jsonrpc/site.py#L186-195 .
It seems that the version is initialized to late in the marked block and early exceptions are handled with the JSON RPC 1.0 spec, because the version_hint is always "1.0".
>>>jsonrpc.register_blueprint(bp)
AttributeError: 'JSONRPC' object has no attribute 'register_blueprint'
I see that its still used in one of the examples (https://github.com/cenobites/flask-jsonrpc/blob/master/examples/modular/api/user.py#L33) but does not appear to be in the main source any longer.
Is there a replacement for this functionality?
I'm getting an "InvalidRequestError: Unterminated string" error when I include an equals sign in a string param.
Test app:
from flask import Flask
from flask_jsonrpc import JSONRPC
app = Flask(__name__)
jsonrpc = JSONRPC(app, '/api')
@jsonrpc.method('echo')
def echo(s):
return s
if __name__ == '__main__':
app.run(debug=True)
Success:
$ curl -i -X POST -d '{"jsonrpc": "2.0", "method": "echo", "params": ["hello"], "id": "1"}' http://localhost:5000/api
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 58
Server: Werkzeug/0.10.4 Python/2.7.5
Date: Fri, 10 Jul 2015 19:56:43 GMT
{
"id": "1",
"jsonrpc": "2.0",
"result": "hello"
}
Unexpected failure:
$ curl -i -X POST -d '{"jsonrpc": "2.0", "method": "echo", "params": ["hello=world"], "id": "1"}' http://localhost:3431/api
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 473
Server: Werkzeug/0.10.4 Python/2.7.5
Date: Fri, 10 Jul 2015 19:56:48 GMT
{
"error": {
"code": -32600,
"data": null,
"executable": "/usr/bin/python",
"message": "InvalidRequestError: Unterminated string starting at: line 1 column 49 (char 48)",
"name": "InvalidRequestError",
"stack": "Traceback (most recent call last):\n File \"/usr/lib/python2.7/site-packages/flask_jsonrpc/site.py\", line 281, in dispatch\n raise InvalidRequestError(e.message)\nInvalidRequestError\n"
},
"id": null,
"result": null
}
I'm on CentOS 7 with up to date packages:
$ sudo pip install flask-jsonrpc --upgrade
Requirement already up-to-date: flask-jsonrpc in /usr/lib/python2.7/site-packages
Requirement already up-to-date: Flask>=0.9 in /usr/lib/python2.7/site-packages (from flask-jsonrpc)
Requirement already up-to-date: Werkzeug>=0.7 in /usr/lib/python2.7/site-packages (from Flask>=0.9->flask-jsonrpc)
Requirement already up-to-date: Jinja2>=2.4 in /usr/lib/python2.7/site-packages (from Flask>=0.9->flask-jsonrpc)
Requirement already up-to-date: itsdangerous>=0.21 in /usr/lib/python2.7/site-packages (from Flask>=0.9->flask-jsonrpc)
Requirement already up-to-date: markupsafe in /usr/lib64/python2.7/site-packages (from Jinja2>=2.4->Flask>=0.9->flask-jsonrpc)
Cleaning up...
Thanks!
There's currently some basic data validation for methods, but it only supports type validation (i.e., verify parameter is dict
, int
, str
, etc.). It would be nice if users could utilize an external library like Cerberus to validate the data inside the extension rather than unpacking all of the variables inside of the view itself.
I could probably get the feature implemented myself and submit a pull request, but as I said in the last issue report I opened, there aren't any contributing guidelines so I'm not sure what the next step of that would be.
Wait for travis-ci/travis-ci#1989
I noticed that the .py scripts do not contain a proper license header but only a copyright line. Please add the contents of COPYING to all code files if they are under the respective license.
When developing an API backend with flask_jsonrpc and a seperate backend API errors are being
sent to the frontend as regular correct 200 responses with the Error encoded as JSON. So far so good and
i can understand that design desision. The built in Web browsable API shows the error message as a normal valid JSONRPC result.
However when the API get's more complex and the Web browsable API becomes to cumbersome to use (because let's say 50 or 100 fields have to be filled to generate a API request) you will want to use your custom frontend. But "errors" are just being sent as valid 200 responses.
It would be nice to (when the debug mode is on) the json error message is also being printed to the python console. Otherwise JSONSRPC error's especially the OtherError's will just dissapear when the frontend does not log them.
It would be a simple change:
exceptions.py line 80 add:
76 if current_app.config['DEBUG']:
77 import sys, traceback
78 error['stack'] = traceback.format_exc()
79 error['executable'] = sys.executable
80 print(error)
Parameters not see in decorators between
Work in url /api/browse
@jsonrpc.method('tag.add')
def tag_add(name):
Not work in url /api/browse
@jsonrpc.method('tag.add')
@exampleDecorator
def tag_add(name):
When flask_jsonrpc is used with browse enabled on a non-root script path, the browse functionality does not work. It just shows a blank page with a header bar.
This appears to be due to within the file views/browse/__init__.py
the function index
starts with:
url_prefix = request.path
but if the application is not deployed to the root URL path this is not correct and should instead be:
url_prefix = request.script_root + request.path
as described in https://flask.palletsprojects.com/en/1.1.x/api/#incoming-request-data
I cannot return the result of db search which contain the type of Decimal
directly.
My solution is like this:
class EnhancedJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
ARGS = ('year', 'month', 'day', 'hour', 'minute',
'second', 'microsecond')
return {'__type__': 'datetime.datetime',
'args': [getattr(obj, a) for a in ARGS]}
elif isinstance(obj, datetime.date):
ARGS = ('year', 'month', 'day')
return {'__type__': 'datetime.date',
'args': [getattr(obj, a) for a in ARGS]}
elif isinstance(obj, datetime.time):
ARGS = ('hour', 'minute', 'second', 'microsecond')
return {'__type__': 'datetime.time',
'args': [getattr(obj, a) for a in ARGS]}
elif isinstance(obj, datetime.timedelta):
ARGS = ('days', 'seconds', 'microseconds')
return {'__type__': 'datetime.timedelta',
'args': [getattr(obj, a) for a in ARGS]}
elif isinstance(obj, decimal.Decimal):
'''
return {'__type__': 'decimal.Decimal',
'args': [str(obj),]}
'''
return float(obj)
else:
return super().default(obj)
class EnhancedJSONDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
super(EnhancedJSONDecoder, self).__init__(*args, object_hook=self.object_hook,
**kwargs)
def object_hook(self, d):
if '__type__' not in d:
return d
o = sys.modules[__name__]
for e in d['__type__'].split('.'):
o = getattr(o, e)
args, kwargs = d.get('args', ()), d.get('kwargs', {})
return o(*args, **kwargs)
def execute_select_sql(sql):
"""excute SELECT SQL """
try:
db = get_db_connect()
cursor = db.cursor()
print 'execute sql is [{}]'.format(sql)
cursor.execute(sql)
data = cursor.fetchall()
try:
json_data = json.dumps(data, cls=EnhancedJSONEncoder)
data = json.loads(json_data, cls=EnhancedJSONDecoder)
except UnicodeDecodeError as e:
data = 'Don not select BLOB!!!'
except Exception as e:
data = repr(e)
except Exception as e:
print repr(e)
raise e
else:
print 'data is [{}]'.format(data)
return data
finally:
try:
db.close()
except:
pass
@jsonrpc.method('run_sql')
def run_sql(sql):
return execute_select_sql(sql)
Sending a boolean as an argument to a route gets encoded as a dictionary -- if you set validate=True
, you'll always get the response '"message": "InvalidParamsError: <type 'dict'> is not the correct type <type 'bool'> for ...', if you do not set validate=True
, then every argument is considered "truthy".
The API works correctly when using curl directly.
The problem can be created by running the app below (Flask 0.10.1, Flask-JSONRPC 0.3), and navigating to http://localhost:5000/api/browse/#/say
from flask import Flask
from flask_jsonrpc import JSONRPC
app = Flask(__name__)
jsonrpc = JSONRPC(app, '/api', enable_web_browsable_api=True)
@jsonrpc.method('say(hi=bool) -> String', validate=True)
def say(hi=False):
if hi:
return "hi"
return "bye"
@jsonrpc.method('nsay(n=int, hi=bool) -> String', validate=True)
def nsay(n=5, hi=False):
if hi:
return n * "hi "
return n * "bye "
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
Hello, make_response return error, becose my result is list.
(Error:The view function did not return a valid response.)
flask_jsonrpc/__init__.py:225: DeprecationWarning: inspect.getargspec() is deprecated since Python 3.0, use inspect.signature() or inspect.getfullargspec()
arg_names = getargspec(f)[0]
Based on pull request 51 which allows setting a value for "data"...
The actual parameters order for Error Class is:
def __init__(self, message=None, code=None, data=None):
In order to set a value for "data" without setting the "message", we must adjust our code and use a named argument:
raise InvalidParamsError(data='This value cannot be an integer.')
But this module (flask-jsonrpc) still raises exceptions using positioned arguments, like:
InvalidRequestError('The method you are trying to access is not availble by GET requests')
It sets 'The method you are trying to access is not availble by GET requests' to message
instead of data
.
"data": null,
"message": "The method you are trying to access is not availble by GET requests",
While the correct should be:
"data": "The method you are trying to access is not availble by GET requests",
"message": "Invalid Request.",
So the problem is: should this module use named argument for setting data
or should the Error class change the parameters order to data
come first to messsage
for the first argument be always a data
by default?
Loading of web page hangs and nothing are shown when no internet.
This happens because download of external google fonts can't be done if no internet connection.
Ubuntu 16, firefox 45.0.1.
No such problem in Chrome.
Data with "+" will raise InvalidRequestError with ServiceProxy.
But it works with API browser.
Hi,
When calling the API from either of these two JS libraries:
I get a 500 error returned and a traceback looking like this:
[2016-08-19 12:35:59,471] ERROR in app: Exception on /api [OPTIONS]
Traceback (most recent call last):
File "/home/flyte/.virtualenvs/herkulex/local/lib/python2.7/site-packages/flask/app.py", line 1988, in wsgi_app
response = self.full_dispatch_request()
File "/home/flyte/.virtualenvs/herkulex/local/lib/python2.7/site-packages/flask/app.py", line 1641, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/flyte/.virtualenvs/herkulex/local/lib/python2.7/site-packages/flask_cors/extension.py", line 188, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/flyte/.virtualenvs/herkulex/local/lib/python2.7/site-packages/flask/app.py", line 1544, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/flyte/.virtualenvs/herkulex/local/lib/python2.7/site-packages/flask/app.py", line 1639, in full_dispatch_request
rv = self.dispatch_request()
File "/home/flyte/.virtualenvs/herkulex/local/lib/python2.7/site-packages/flask/app.py", line 1625, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/flyte/.virtualenvs/herkulex/local/lib/python2.7/site-packages/flask_jsonrpc/__init__.py", line 163, in wrapper
response_obj, status_code = site.dispatch(request, method)
File "/home/flyte/.virtualenvs/herkulex/local/lib/python2.7/site-packages/flask_jsonrpc/site.py", line 362, in dispatch
raw_data = extract_raw_data_request(request)
File "/home/flyte/.virtualenvs/herkulex/local/lib/python2.7/site-packages/flask_jsonrpc/helpers.py", line 82, in extract_raw_data_request
return text_type(raw_data, encoding)
TypeError: decoding Unicode is not supported
127.0.0.1 - - [19/Aug/2016 12:35:59] "OPTIONS /api HTTP/1.1" 500 -
I'm able to consume the API fine using the Python ServiceProxy.
Is this intended behavior? If so, how do I stop the JS clients from using Unicode?
Thank you.
Hello,
error OtherError message looks like
{
"code": -32001,
"data": null,
"message": "OtherError: Invalid Terminal ID u'tid01x'",
"name": "OtherError"
}
but a a malformed JSON RPC request error looks like
{
"error": {
"code": -32000,
"message": "Not a valid JSON RPC request"
},
"id": null,
"jsonrpc": "2.0"
}
Every error message should be JSON RPC 2.0 error response
moreover they can sometimes have id
different from null
so
we should provide a way to set id (maybe in constructor with id=None as default value)
Kind regards
When i'm give high load (5-10 connections at second from browsers via ajax) on simple server, writen with this lib, i have 'connection timed out'.
Without high load all work fine.
all json-rpc methods simple and no any special (no db connections or any long operations).
I did't find how can i use this two types to auth. It is not a good idea for me to send username and password as params. If somebody know how to use basic auth with this component please tell me. I am new in python and flask :)
There is an error at function extract_raw_data_request._extract_raw_data_request in file helpers.py, the not right code is return list(request.form.to_dict().keys())[0]
, this sentence maybe get a str object then will meet an Unicode Error, but I think it should be a bytes object.
I suggest correct it as return list(request.form.to_dict().keys())[0] if instance(list(request.form.to_dict().keys())[0], bytes) else list(request.form.to_dict().keys())[0].encode()
I currently can't find a way to return a custom error code easily. And, along the same idea, I can't find any way to change the return value at all except for what's returned in the "result" section.
I'm not actually sure at all how to do this :)
Run command:
$ find . -name "*.py" | xargs 2to3
I'd like to know how blueprints actually work in Flask-JSONRPC; the only thing the examples look to be doing is registering the blueprint itself, but the methods on it are registered to the toplevel JSONRPC instance, instead of one for the blueprint itself:
from base_app import jsonrpc # the one from the toplevel app
from flask import Blueprint
bp = Blueprint(__name__)
# if I had a method here:
@bp.route("/')
def method():
pass
# but for the JSONRPC, the blueprint doesn't seem to be used:
@jsonrpc.method("BluePrint.a_method")
def a_method():
pass
I'd expect something like this:
from flask_jsonrpc import JSONRPC
from flask import Blueprint
bp = Blueprint(__name__)
bprpc = JSONRPC(blueprint=bp)
@bprpc.method("a_method")
def a_method():
pass
from base_app import jsonrpc
jsonrpc.register_blueprint("TopLevel", bprpc)
This would end up being called as TopLevel.a_method.
I'm not sure this makes sense, but it lines up with my intuition about how blueprints work.
Hi,
we are currently writing a small, encrypted chat service with json-rpc. While reporting an issue to the json-rpc implementation we use on client-side, we think that we might found an additional bug in this implementation.
Here is a description of the bug: cinemast/libjson-rpc-cpp#119 (comment)
Thanks in advance!
I'm using flask-jsonrpc for a project of mine, and I can't seem to find a way to report or log the logging or exceptions that are caught in the repository.
For instance, if someone tries to use a non-existant method, or sends a bad parameter, there is no way for me to log that I can find.
EDIT: After I read through the code, I've realized that I can't override or use the logging facility because there is no logging facility. So I guess this isn't a bug request or issue, as much as it is a feature request for the addition of a logging facility.
Some basic usage would be logging when a user accesses a method, what method is accessed, if there is/was an error with the JSONRPC backend, etc.
If necessary, I can add some code and submit a pull request. Just let me know what the preferred path is for this. I can't find any contributing guidelines.
It would be nice to not restrict this to work on plain functions or static methods.
I think a lot of people would like to use this library like this:
from flask import Flask
from flask_jsonrpc import JSONRPC
class Test:
app = Flask(__name__)
jsonrpc = JSONRPC(app, '/api', enable_web_browsable_api=True)
@jsonrpc.method('App.sum(Number, Number) -> Number', validate=True)
def sum_(self, a, b):
return a + b
def run(host='0.0.0.0', port=3500):
self.app.run(host=host, port=port, debug=True)
if __name__ == '__main__':
Test().app.run()
Running curl would require 3 arguments, but it does "work":
$ curl -v -XPOST -H "Content-type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method" : "App.sum", "params":[1,1,2]}' 'http://localhost:5000/api'
{"id":1,"jsonrpc":"2.0","result":3}
Python >=2.7 or 3.x are priorities.
It would be amazing if flask-jsonrpc could auto-serve (potentially jQuery-based) Javascript classes generated from the registered methods, as a script that can be easily loaded by HTML in a browser. As it is I would still have to write the browser client part of the transaction.
If a string passed to the JSON-RPC api contains the character =, the API returns "Invalid Request Error". This is problematic, especially for Base64 encoded text, as the = character is padded to the end of the string.
In init.py (line 228-229) the authentication backend assumes that a username and password is given in the check_auth function that is given in the api.method(...., authenticated=check_auth) function.
# TODO: this is an assumption
X['arg_names'] = ['username', 'password'] + X['arg_names']
X['name'] = _inject_args(X['name'], ('String', 'String'))
If you change this in:
auth_args = [x for x in authenticated.__code__.co_varnames[:authenticated.__code__.co_argcount]]
X['arg_names'] = auth_args + X['arg_names']
X['name'] = _inject_args(X['name'], tuple(["String"]) * len(auth_args))
It would dynamically use the arguments that you define in the handler in ...method.(...authenticated=check_auth). The tuple(["String"]) * len(auth_args) would however assume that the arguments used are always Strings. But i don't see why not. In that way you could use:
def check_auth(token):
<do some magic token checking here for example>
Or any other means of authentication, instead of username and password, with any arbitrary number of arguments without having to declare them specifically in every decorator (as i saw in the Issue related to this one) , which seems a bit more DRY to me.
update: added
[:authenticated.code.co_argcount]
To only extract the agruments passed to the check_auth function, and not the internal variables
from flask_wtf import CsrfProtect
CsrfProtect(app)
from flask_jsonrpc import JSONRPC
jsonrpc = JSONRPC(app, '/JOB/script/call/jsonrpc2')
@jsonrpc.method('create_script_interface')
def get( ):
pass
the result is :
<title>400 Bad Request</title>The CSRF token is missing.
[run]
server=ServiceProxy('http://localhost:5000/api')
server.echo({'arg': 'test'})
[result]
hacking the code I found out that the parameter is encapsulated into array, instead of object.
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.