使用过steem JSON API的都知道我们调用JSON API有两种方式。以往大多数时候这两种方式都是正常工作的,但是最近遇到一个API,工作不正常,所以探究了一下到底是哪里出了问题。
(图源 :pixabay)
调用方式
说到两种调用方式,我们以获取用户信息的JSON为例:
方式一
{"jsonrpc": "2.0", "method": "call", "params": ["database_api", "get_accounts", [["oflyhigh"]]], "id": 1}
方式二
{"jsonrpc": "2.0", "method": "database_api.get_accounts", "params": [["oflyhigh"]], "id": 1}
在早些时候这两种工作方式都是正常的,但是如果我们现在使用https://api.steemit.com
这个节点来调用上述两个API,则会发现方式二返回错误:
看了一下代码,get_accounts已经从database_api移到condenser_api中,也就是说第二种调用方式的返回才是正确的。
处理方式的区别
那么调用方式一和方式二,steem节点都是如何处理的呢?
这部分代码在json_rpc_plugin.cpp中
处理rpc的请求会放置到如下函数中
void json_rpc_plugin_impl::rpc_jsonrpc( const fc::variant_object& request, json_rpc_response& response )
进去之后会根据JSON的构成进行解析process_params
从上述代码中不难看出,尽管JSON的格式有所区别,但是最终都是提取出api、method、args
然后再进行下一步处理,也就是说殊途同归。
JUSSI
既然尽管JSON的构成有所差异,但是最终处理是殊途同归,那么上述两个调用应该返回同样的结果才对呢?要么是都好用,要么是通通不好用,为何方式一好用而方式二不好用呢?(确切地说方式二返回的错误信息才是正确的)
答案在于JUSSI,简单地说,它是steemd之上的一个缓存层,信息发送给steemd之前都在这里预处理一遍,然后再发送给steemd.
对应 RPC而言,它对类似方式一的数据进行了处理,不过把api部分处理成condenser_api
,美其名曰:translate_to_appbase
,所以两者的调用结果大相径庭。
好处 vs 坏处
对应我们从老旧的API构成以及使用老旧的调用方式而言,JUSSI自动帮我们处理了转换,比如我一直使用诸如方式一的调用,尽管是错误的,但是因为JUSSI的存在,我的错误调用反而能返回正确的结果,颇为神奇。
但是我们来看下列JSON:
{"jsonrpc": "2.0", "method": "call", "params": ["tags_api", "get_discussion", []], "id": 1}
忽略参数部分,这个JSON结构是正确的,调用后应该返回如下信息(表示我们没给对参数):
‘message’: “Bad Cast:Invalid cast from type ‘array_type’ to Object”},
但是上述调用却返回
‘message’: ‘Assert Exception:method_itr != api_itr->second.end(): ‘
‘Could not find method get_discussion’},
也就说因为JUSSI的存在,给出了完全错误的出错信息,真是成也萧何败也萧何呀。
结论
尽管JUSSI增加了容错性,使得老旧的API调用依旧可用,但是却蒙蔽了我们的双眼,让我们不知道自己使用了错误的调用方式或者说调用了错误的API。同时因为JUSSI的存在,使得一些正常的调用反而出错。所以从API调用这个角度而言,JUSSI真的让人爱不起来又恨不起来。
不过通过这次学习,我至少知道了STEEMD的API变动挺大,以后应该把程序中错误的调用方式都切换到正确的方式上来,尽量不要依赖于JUSSI的容错性。
This page is synchronized from the post: JUSSI: 想说爱你并不是很容易的事