Update
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "jsonrpc"
|
||||
version = "1.0"
|
||||
version = "2.0"
|
||||
authors = [
|
||||
{ name="RemiZOffAlex", email="remizoffalex@gmail.com" },
|
||||
]
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
__author__ = 'RemiZOffAlex'
|
||||
__email__ = 'remizoffalex@mail.ru'
|
||||
|
||||
import json
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
@@ -27,7 +26,7 @@ class Response:
|
||||
|
||||
|
||||
class Method:
|
||||
def __init__(self, function, middlewares = [], debug: bool = False):
|
||||
def __init__(self, function, middlewares=[], debug: bool = False):
|
||||
self.function = function
|
||||
self.middlewares = middlewares
|
||||
self.debug = debug
|
||||
@@ -65,11 +64,9 @@ class Method:
|
||||
response = middleware(query)
|
||||
return response
|
||||
|
||||
|
||||
response = self.exec_function(query)
|
||||
return response
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return '<{}>'.format(self.function)
|
||||
|
||||
@@ -86,15 +83,15 @@ class JSONRPC:
|
||||
self.methods = {}
|
||||
self.debug = debug
|
||||
|
||||
def method(self, name: str, middlewares = None):
|
||||
def method(self, name: str, middlewares=None):
|
||||
"""Декоратор метода
|
||||
"""
|
||||
assert len(name) > 0, 'Не указано имя метода'
|
||||
|
||||
def wrap(function):
|
||||
method = Method(
|
||||
function = function,
|
||||
middlewares = middlewares
|
||||
function=function,
|
||||
middlewares=middlewares
|
||||
)
|
||||
self.methods[name] = method
|
||||
return function
|
||||
@@ -151,31 +148,31 @@ class JSONRPC:
|
||||
def validate(self, query):
|
||||
"""Валидация запроса
|
||||
"""
|
||||
keys = query.keys()
|
||||
if 'id' not in query:
|
||||
return InvalidRequestError(
|
||||
id=query['id'],
|
||||
message=f'Некорректный запрос: {query}'
|
||||
).__json__()
|
||||
|
||||
if 'method' not in query:
|
||||
return InvalidRequestError(
|
||||
id=query['id'],
|
||||
result = InvalidRequestError(
|
||||
message=f'Некорректный запрос: {query}'
|
||||
).__json__()
|
||||
)
|
||||
if 'id' in query:
|
||||
result.id = query['id']
|
||||
return result
|
||||
|
||||
def process(self, query):
|
||||
"""Выполнение метода
|
||||
"""
|
||||
self.validate(query)
|
||||
result = self.validate(query)
|
||||
if isinstance(result, JSONRPCError):
|
||||
return result
|
||||
name = query['method']
|
||||
if name not in self.methods:
|
||||
if 'id' in query:
|
||||
__id = query['id']
|
||||
else:
|
||||
__id = None
|
||||
result = MethodNotFoundError(
|
||||
query['id'],
|
||||
message=f'Метод не найден: {name}'
|
||||
message=f'Метод не найден: {name}',
|
||||
id=__id
|
||||
)
|
||||
return result.__json__()
|
||||
|
||||
return result
|
||||
|
||||
method = self.methods[name]
|
||||
|
||||
@@ -198,11 +195,14 @@ class JSONRPC:
|
||||
# message=traceback.format_exc()
|
||||
)
|
||||
else:
|
||||
response = Response(
|
||||
id=query['id'],
|
||||
result=response
|
||||
)
|
||||
result = response.__json__()
|
||||
if 'id' in query:
|
||||
response = Response(
|
||||
id=query['id'],
|
||||
result=response
|
||||
)
|
||||
else:
|
||||
return
|
||||
result = response
|
||||
return result
|
||||
|
||||
def __call__(self, queries):
|
||||
@@ -213,7 +213,9 @@ class JSONRPC:
|
||||
elif isinstance(queries, list):
|
||||
result = []
|
||||
for query in queries:
|
||||
result.append(self.process(query))
|
||||
response = self.process(query)
|
||||
if response:
|
||||
result.append(response)
|
||||
return result
|
||||
|
||||
def __getitem__(self, key):
|
||||
|
||||
@@ -2,19 +2,30 @@ __author__ = 'RemiZOffAlex'
|
||||
__email__ = 'remizoffalex@mail.ru'
|
||||
|
||||
import jinja2
|
||||
import logging
|
||||
import pathlib
|
||||
import aiohttp_jinja2
|
||||
|
||||
from aiohttp.web import Response, json_response
|
||||
|
||||
from .. import JSONRPC
|
||||
from ..exceptions import ParseError
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
pathlib.Path(__file__).parent.resolve()
|
||||
|
||||
|
||||
class APIHandler:
|
||||
def __init__(self, jsonrpc):
|
||||
def __init__(
|
||||
self,
|
||||
jsonrpc,
|
||||
debug: bool = False
|
||||
):
|
||||
self.jsonrpc = jsonrpc
|
||||
self.debug = debug
|
||||
if self.debug:
|
||||
log.debug('Connect JSON-RPC to aiohttp complete')
|
||||
|
||||
@aiohttp_jinja2.template('api_browse.html')
|
||||
async def get(self, request) -> Response:
|
||||
@@ -25,9 +36,16 @@ class APIHandler:
|
||||
return pagedata
|
||||
|
||||
async def post(self, request) -> Response:
|
||||
json_data = await request.json()
|
||||
result = self.jsonrpc(json_data)
|
||||
return json_response(result)
|
||||
try:
|
||||
json_data = await request.json()
|
||||
result = self.jsonrpc(json_data)
|
||||
return json_response(result)
|
||||
except ValueError as e:
|
||||
log.error('invalid json: %s', request_data)
|
||||
log.exception(e)
|
||||
raise ParseError(
|
||||
message={'message': 'Invalid JSON: {0!r}'.format(request_data)}
|
||||
)
|
||||
|
||||
|
||||
def api_init(app, jsonrpc: JSONRPC, rule: str = '/api'):
|
||||
@@ -38,6 +56,6 @@ def api_init(app, jsonrpc: JSONRPC, rule: str = '/api'):
|
||||
pathlib.Path(__file__).parent.resolve() / 'templates'
|
||||
)
|
||||
)
|
||||
handler = APIView(jsonrpc)
|
||||
handler = APIHandler(jsonrpc)
|
||||
app.router.add_route('GET', rule, handler.get)
|
||||
app.router.add_route('POST', rule, handler.post)
|
||||
|
||||
@@ -6,6 +6,7 @@ from flask.views import MethodView
|
||||
from flask import jsonify, Response, request, render_template
|
||||
|
||||
from ..exceptions import ParseError
|
||||
from ..serialize import JSONRPCEncoder
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -20,9 +21,13 @@ def to_json(
|
||||
try:
|
||||
return json.loads(request_data)
|
||||
except ValueError as e:
|
||||
print('invalid json:', request_data)
|
||||
log.error('invalid json: %s', request_data)
|
||||
log.exception(e)
|
||||
raise ParseError(data={'message': 'Invalid JSON: {0!r}'.format(request_data)})
|
||||
result = ParseError(
|
||||
message={'message': 'Invalid JSON: {0!r}'.format(request_data)}
|
||||
)
|
||||
return result
|
||||
# raise ValueError('Invalid JSON')
|
||||
|
||||
|
||||
@@ -43,8 +48,12 @@ class APIView(MethodView):
|
||||
return body
|
||||
|
||||
def post(self):
|
||||
if self.debug:
|
||||
print('request.data', request.data)
|
||||
json_data = to_json(request.data)
|
||||
result = self.jsonrpc(json_data)
|
||||
if self.debug:
|
||||
print(result)
|
||||
log.debug(result)
|
||||
return jsonify(result)
|
||||
# return jsonify(result)
|
||||
return json.dumps(result, cls=JSONRPCEncoder)
|
||||
|
||||
@@ -30,12 +30,14 @@ class Client:
|
||||
self.url,
|
||||
data=payload,
|
||||
headers=self.headers
|
||||
).json()
|
||||
)
|
||||
print('content', response.content)
|
||||
result = response.json()
|
||||
|
||||
assert 'jsonrpc' in response
|
||||
assert 'id' in response
|
||||
assert response["jsonrpc"] in ['2.0', '3.0']
|
||||
if '3.0' in response["jsonrpc"]:
|
||||
assert 'meta' in response
|
||||
assert 'jsonrpc' in result
|
||||
assert 'id' in result
|
||||
assert result["jsonrpc"] in ['2.0', '3.0']
|
||||
if '3.0' in result["jsonrpc"]:
|
||||
assert 'meta' in result
|
||||
|
||||
return response
|
||||
return result
|
||||
|
||||
19
src/jsonrpc/serialize.py
Normal file
19
src/jsonrpc/serialize.py
Normal file
@@ -0,0 +1,19 @@
|
||||
__author__ = 'RemiZOffAlex'
|
||||
__email__ = 'remizoffalex@mail.ru'
|
||||
|
||||
import json
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from .exceptions import JSONRPCError
|
||||
|
||||
|
||||
class JSONRPCEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj, datetime):
|
||||
return obj.isoformat()
|
||||
elif isinstance(obj, JSONRPCError):
|
||||
return obj.__json__()
|
||||
elif hasattr(obj, '__dict__'):
|
||||
return obj.__dict__
|
||||
return super().default(obj)
|
||||
Reference in New Issue
Block a user