在websockets传输之上使用aiohttp实现json-rpc 2.0服务器和客户端

aiohttp-json-rpc的Python项目详细描述


https://img.shields.io/pypi/v/aiohttp-json-rpc.svghttps://img.shields.io/travis/pengutronix/aiohttp-json-rpc/master.svg?label=Linux%20build%20%40%20Travis%20CIhttps://img.shields.io/pypi/pyversions/aiohttp-json-rpc.svg

aiohttp json rpc

使用aiohttp实现JSON-RPC 2.0 Specification

ProtocolSupport
Websocketsince v0.1
POSTTODO
GETTODO

安装

pip install aiohttp-json-rpc

使用量

可以使用rpc.add_method()添加rpc方法。

所有rpc方法都被传递一个aiohttp_json_rpc.communicaton.JsonRpcRequest

服务器

下面的代码实现了一个简单的rpc服务器,它为localhost:8080上的方法ping提供服务。

fromaiohttp.webimportApplication,run_appfromaiohttp_json_rpcimportJsonRpcimportasyncioasyncdefping(request):return'pong'if__name__=='__main__':loop=asyncio.get_event_loop()rpc=JsonRpc()rpc.add_methods(('',ping),)app=Application(loop=loop)app.router.add_route('*','/',rpc.handle_request)run_app(app,host='0.0.0.0',port=8080)

客户端(js)

下面的代码实现了一个连接到上面服务器的简单rpc客户机 并将所有传入的消息打印到控制台。

<scriptsrc="//code.jquery.com/jquery-2.2.1.js"></script><script>varws=newWebSocket("ws://localhost:8080");varmessage_id=0;ws.onmessage=function(event){console.log(JSON.parse(event.data));}functionws_call_method(method,params){varrequest={jsonrpc:"2.0",id:message_id,method:method,params:params}ws.send(JSON.stringify(request));message_id++;}</script>

这些是服务器在调用ws_call_method时将给出的响应示例。

--> ws_call_method("get_methods")
<--{"jsonrpc":"2.0","result":["get_methods","ping"],"id":1}--> ws_call_method("ping")
<--{"jsonrpc":"2.0","method":"ping","params":"pong","id":2}

客户端(python)

还有python客户机,可以使用如下:

fromaiohttp_json_rpcimportJsonRpcClientasyncdefping_json_rpc():"""Connect to ws://localhost:8080/, call ping() and disconnect."""rpc_client=JsonRpcClient()try:awaitrpc_client.connect('localhost',8080)call_result=awaitrpc_client.call('ping')print(call_result)# prints 'pong' (if that's return val of ping)finally:awaitrpc_client.disconnect()asyncio.get_event_loop().run_until_complete(ping_json_rpc())

或者使用异步上下文管理器接口:

fromaiohttp_json_rpcimportJsonRpcClientContextasyncdefjrpc_coro():asyncwithJsonRpcClientContext('ws://localhost:8000/rpc')asjrpc:# `some_other_method` will get request.params filled with `args` and# `kwargs` keys:method_res=awaitjrpc.some_other_method('arg1',key='arg2')returnmethod_resasyncio.get_event_loop().run_until_complete(jrpc_coro())

功能

错误处理

error specification中指定但invalidparamserror无效的所有错误都在内部处理。

如果用错误的参数调用了coroutine,则可以引发一个aiohttp_json_rpc.RpcInvalidParamsError,而不是自己发送一个错误。

jsonrpc协议定义了服务器定义错误的范围。 aiohttp_json_rpc.RpcGenericServerDefinedError实现此功能。

fromaiohttp_json_rpcimportRpcInvalidParamsErrorasyncdefadd(request):try:a=params.get('a')b=params.get('b')returna+bexceptKeyError:raiseRpcInvalidParamsErrorasyncdefadd(request):raiseRpcGenericServerDefinedError(error_code=-32050,message='Computer says no.',)

错误日志记录

由rpc方法引起的每个回溯都将被捕获并记录下来。

rpc将发送一个rpc服务器错误,并像没有发生任何事情一样继续。

asyncdefdivide(request):return1/0# will raise a ZeroDivisionError
ERROR:JsonRpc: Traceback (most recent call last):
ERROR:JsonRpc:   File "aiohttp_json_rpc/base.py", line 289, in handle_websocket_request
ERROR:JsonRpc:     rsp = yield from methods[msg['method']](ws, msg)
ERROR:JsonRpc:   File "./example.py", line 12, in divide
ERROR:JsonRpc:     return 1 / 0
ERROR:JsonRpc: ZeroDivisionError: division by zero

发布订阅

rpc对象的任何客户端都可以使用内置的rpc方法subscribe()订阅主题。

可以使用rpc.add_topics添加主题。

身份验证

auth系统的工作方式与django中的decorators类似。 有关详细信息,请参阅相应的django文档。

DecoratorDjango Equivalent
aiohttp_json_rpc.django.auth.login_requireddjango.contrib.auth.decorators.login_required
aiohttp_json_rpc.django.auth.permission_requireddjango.contrib.auth.decorators.permission_required
aiohttp_json_rpc.django.auth.user_passes_testdjango.contrib.auth.decorators.user_passes_test
fromaiohttp_json_rpc.authimport(permission_required,user_passes_test,login_required,)fromaiohttp_json_rpc.auth.djangoimportDjangoAuthBackendfromaiohttp_json_rpcimportJsonRpc@login_required@permission_required('ping')@user_passes_test(lambdauser:user.is_superuser)asyncdefping(request):return'pong'if__name__=='__main__':rpc=JsonRpc(auth_backend=DjangoAuthBackend())rpc.add_methods(('',ping),)rpc.add_topics(('foo',[login_required,permission_required('foo')]))

课程参考

类aiohttp_json_rpc.jsonrpc(对象)

方法

def add_methods(self, *args, prefix='')

参数必须是包含前缀为字符串(可能为空)和模块的元组, 对象、协同程序或导入字符串。

如果第二个参数是module或object,则将添加其中的所有协程。

async def get_methods()
返回所有可用rpc方法的列表。
def filter(self, topics)

返回已订阅给定主题的所有客户端上的生成器。

主题可以是字符串或字符串列表。

async def notify(self, topic, data)

向订阅给定主题的所有已连接客户端发送rpc通知。

数据必须是可序列化的json。

使用filter()

async def subscribe(topics)

订阅主题。

主题可以是字符串或字符串列表。

async def unsubscribe(topics)

取消订阅主题。

主题可以是字符串或字符串列表。

async def get_topics()
将可订阅主题作为字符串列表。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java JavaFX TableView更新单元格,不更新对象值   在扫描器中使用分隔符的java   java OkHttp 4.9.2,连接无法重用,导致端口耗尽   eclipse中的c JNI:运行Java代码   java是否在出厂的所有硬件设备中都有/mnt/sdcard/Android/data文件夹(或等效文件夹)?   Java,在eclipse中访问资源文件夹中的图像   java为什么Bluemix dashDB操作抛出SqlSyntaxErrorException,SQLCODE=1667?   JavaHtmlUnitWebClient。getPage不处理javascript   Google API认证的java问题   java如何将JSON数组反序列化为Apache beam PCollection<javaObject>   ServerSocket停止接收命令,java/安卓   来自Java类的安卓 Toast消息   java如何自动重新加载应用程序引擎开发服务器?   java是否可以尝试/捕获一些东西来检查是否抛出了异常?   java如何做到这一点当我按下load game时,它不仅会加载信息,还会将您带到游戏中?   Java选项Xmx代表什么?   Java映射,它在插入时打印值   设置“ulimit c unlimited”后,java无法生成系统核心转储