92 lines
2.8 KiB
Python
92 lines
2.8 KiB
Python
from __future__ import absolute_import
|
|
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.conf.urls import url
|
|
from django.conf import settings
|
|
from django.http import HttpResponse, HttpResponseNotAllowed
|
|
import copy
|
|
import json
|
|
import logging
|
|
import time
|
|
|
|
from ..exceptions import JSONRPCInvalidRequestException
|
|
from ..jsonrpc import JSONRPCRequest
|
|
from ..manager import JSONRPCResponseManager
|
|
from ..utils import DatetimeDecimalEncoder
|
|
from ..dispatcher import Dispatcher
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def response_serialize(obj):
|
|
""" Serializes response's data object to JSON. """
|
|
return json.dumps(obj, cls=DatetimeDecimalEncoder)
|
|
|
|
|
|
class JSONRPCAPI(object):
|
|
def __init__(self, dispatcher=None):
|
|
self.dispatcher = dispatcher if dispatcher is not None \
|
|
else Dispatcher()
|
|
|
|
@property
|
|
def urls(self):
|
|
urls = [
|
|
url(r'^$', self.jsonrpc, name='endpoint'),
|
|
]
|
|
|
|
if getattr(settings, 'JSONRPC_MAP_VIEW_ENABLED', settings.DEBUG):
|
|
urls.append(
|
|
url(r'^map$', self.jsonrpc_map, name='map')
|
|
)
|
|
|
|
return urls
|
|
|
|
@csrf_exempt
|
|
def jsonrpc(self, request):
|
|
""" JSON-RPC 2.0 handler."""
|
|
if request.method != "POST":
|
|
return HttpResponseNotAllowed(["POST"])
|
|
|
|
request_str = request.body.decode('utf8')
|
|
try:
|
|
jsonrpc_request = JSONRPCRequest.from_json(request_str)
|
|
except (TypeError, ValueError, JSONRPCInvalidRequestException):
|
|
response = JSONRPCResponseManager.handle(
|
|
request_str, self.dispatcher)
|
|
else:
|
|
jsonrpc_request.params = jsonrpc_request.params or {}
|
|
jsonrpc_request_params = copy.copy(jsonrpc_request.params)
|
|
if isinstance(jsonrpc_request.params, dict):
|
|
jsonrpc_request.params.update(request=request)
|
|
if isinstance(jsonrpc_request.params, list):
|
|
jsonrpc_request.params.insert(0, request)
|
|
|
|
t1 = time.time()
|
|
response = JSONRPCResponseManager.handle_request(
|
|
jsonrpc_request, self.dispatcher)
|
|
t2 = time.time()
|
|
logger.info('{0}({1}) {2:.2f} sec'.format(
|
|
jsonrpc_request.method, jsonrpc_request_params, t2 - t1))
|
|
|
|
if response:
|
|
response.serialize = response_serialize
|
|
response = response.json
|
|
|
|
return HttpResponse(response, content_type="application/json")
|
|
|
|
def jsonrpc_map(self, request):
|
|
""" Map of json-rpc available calls.
|
|
|
|
:return str:
|
|
|
|
"""
|
|
result = "<h1>JSON-RPC map</h1><pre>{0}</pre>".format("\n\n".join([
|
|
"{0}: {1}".format(fname, f.__doc__)
|
|
for fname, f in self.dispatcher.items()
|
|
]))
|
|
return HttpResponse(result)
|
|
|
|
|
|
api = JSONRPCAPI()
|