def sql_select(self): stmt = self.request.params['sql'] params = self.request.params['params'] engine_id = self.request.params['engine_id'] # Validate hash hash = hashlib.sha1( bytes_(self.request.exc_history.token + stmt + params)).hexdigest() if hash != self.request.params['hash']: raise HTTPBadRequest('Bad token in request') # Make sure it is a select statement if not stmt.lower().strip().startswith('select'): raise HTTPBadRequest('Not a SELECT SQL statement') if not engine_id: raise HTTPBadRequest('No valid database engine') engine = getattr(self.request.registry, 'pdtb_sqla_engines')\ [int(engine_id)]() params = json.loads(params) result = engine.execute(stmt, params) return { 'result': result.fetchall(), 'headers': result.keys(), 'sql': format_sql(stmt), 'duration': float(self.request.params['duration']), }
def test_jsonrpc_endpoint_batch_request(self): from pyramid.interfaces import IViewClassifier rpc_iface = self._registerRouteRequest('JSON-RPC') view1 = DummyView({'name': 'Smith'}) self._registerView(view1, 'echo1', IViewClassifier, rpc_iface, None) view2 = DummyView({'name': 'John Doe'}) self._registerView(view2, 'echo2', IViewClassifier, rpc_iface, None) request_data = [ {'jsonrpc': '2.0', 'method': 'echo1', 'id': 'echo1-rpc', 'params':[13]}, {'jsonrpc': '2.0', 'method': 'echo2', 'id': 'echo2-rpc', 'params':[13]}, ] request = self._makeDummyRequest(request_data) response = self._callFUT(request) self.assertEqual(response.content_type, 'application/json') data = json.loads(response.body) self.assertEqual(len(data), 2) res1 = data[0] self.assertEqual(res1['id'], 'echo1-rpc') self.assertEqual(res1['result'], {'name': 'Smith'}) res2 = data[1] self.assertEqual(res2['id'], 'echo2-rpc') self.assertEqual(res2['result'], {'name': 'John Doe'})
def test_jsonrpc_endpoint_batch_request_with_error(self): from pyramid.interfaces import IViewClassifier from pyramid_rpc.jsonrpc import JsonRpcInternalError rpc_iface = self._registerRouteRequest('JSON-RPC') view1 = DummyView({'name': 'Smith'}) self._registerView(view1, 'echo1', IViewClassifier, rpc_iface, None) view2 = DummyView(raise_exception=Exception) self._registerView(view2, 'echo2', IViewClassifier, rpc_iface, None) request_data = [ {'jsonrpc': '2.0', 'method': 'echo1', 'id': 'echo1-rpc', 'params':[13]}, {'jsonrpc': '2.0', 'method': 'echo2', 'id': 'echo2-rpc', 'params':[13]}, ] request = self._makeDummyRequest(request_data) response = self._callFUT(request) self.assertEqual(response.content_type, 'application/json') data = json.loads(response.body) self.assertEqual(len(data), 2) res1 = data[0] self.assertEqual('echo1-rpc', res1['id']) self.assertEqual({'name': 'Smith'}, res1['result']) res2 = data[1] self.assertEqual('echo2-rpc', res2['id']) self.assertEqual(res2['error']['code'], JsonRpcInternalError.code)
def sql_select(self): stmt = self.request.params["sql"] params = self.request.params["params"] engine_id = self.request.params["engine_id"] # Validate hash hash = hashlib.sha1(bytes_(self.request.exc_history.token + stmt + params)).hexdigest() if hash != self.request.params["hash"]: raise HTTPBadRequest("Bad token in request") # Make sure it is a select statement if not stmt.lower().strip().startswith("select"): raise HTTPBadRequest("Not a SELECT SQL statement") if not engine_id: raise HTTPBadRequest("No valid database engine") engine = getattr(self.request.registry, "pdtb_sqla_engines")[int(engine_id)]() params = json.loads(params) result = engine.execute(stmt, params) return { "result": result.fetchall(), "headers": result.keys(), "sql": format_sql(stmt), "duration": float(self.request.params["duration"]), }
def test_it(self): try: # Pyramid 1.1 from pyramid.renderers import null_renderer renderer = null_renderer except ImportError: # Pyramid 1.0 renderer = None from pyramid.config import Configurator from pyramid_rpc.jsonrpc import jsonrpc_endpoint from pyramid_rpc.jsonrpc import JsonRpcViewMapper config = Configurator() config.add_route('JSON-RPC', 'apis/rpc') config.add_view(jsonrpc_endpoint, route_name='JSON-RPC') def dummy_rpc(request, a, b): return a + b config.add_view(route_name='JSON-RPC', name='dummy_rpc', view=dummy_rpc, mapper=JsonRpcViewMapper, renderer=renderer) config.add_route('JSON-RPC-CLS', 'apis/rpc/cls') config.add_view(jsonrpc_endpoint, route_name='JSON-RPC-CLS') config.add_view(route_name='JSON-RPC-CLS', name='dummy_rpc', view=DummyView, mapper=JsonRpcViewMapper, renderer=renderer) app = config.make_wsgi_app() import webtest app = webtest.TestApp(app) params = {'jsonrpc': '2.0', 'method': 'dummy_rpc', 'params': [2, 3], 'id': 'test'} body = json.dumps(params) res = app.post('/apis/rpc', params=body, content_type='application/json') data = json.loads(res.body) self.assertEqual(data['id'], 'test') self.assertEqual(data['jsonrpc'], '2.0') self.assertEqual(data['result'], 5) res = app.post('/apis/rpc/cls', params=body, content_type='application/json') data = json.loads(res.body) self.assertEqual(data['id'], 'test') self.assertEqual(data['jsonrpc'], '2.0') self.assertEqual(data['result'], 5)
def test_jsonrpc_endpoint_invalid_version(self): from pyramid_rpc.jsonrpc import JsonRpcRequestInvalid request_data = {'jsonrpc': '1.0'} request = self._makeDummyRequest(request_data) response = self._callFUT(request) data = json.loads(response.body) self.assertEqual(data['error']['code'], JsonRpcRequestInvalid.code)
def test_jsonrpc_endpoint_not_found(self): from pyramid_rpc.jsonrpc import JsonRpcMethodNotFound request_data = {'jsonrpc': '2.0', 'id': 'nothing-rpc', 'method': 'nothing', 'params':[13]} request = self._makeDummyRequest(request_data) response = self._callFUT(request) data = json.loads(response.body) self.assertEqual(data['error']['code'], JsonRpcMethodNotFound.code)
def test_jsonrpc_endpoint_invalid_request(self): from pyramid_rpc.jsonrpc import JsonRpcRequestInvalid request = self._makeDummyRequest() request.body = "10" request.content_length = len(request.body) request.matched_route = DummyRoute('JSON-RPC') response = self._callFUT(request) data = json.loads(response.body) self.assertEqual(data['error']['code'], JsonRpcRequestInvalid.code)
def test_it_with_invalid_body(self): config = self.config config.include('pyramid_rpc.jsonrpc') config.add_jsonrpc_endpoint('rpc', '/api/jsonrpc') app = config.make_wsgi_app() app = TestApp(app) resp = app.post('/api/jsonrpc', content_type='application/json', params='{') self.assertEqual(resp.status_int, 200) self.assertEqual(resp.content_type, 'application/json') result = json.loads(resp.body) self.assertEqual(result['jsonrpc'], '2.0') self.assertEqual(result['error']['code'], -32700)
def test_jsonrpc_endpoint(self): rpc_iface = self._registerRouteRequest('JSON-RPC') from pyramid.interfaces import IViewClassifier view = DummyView({'name': 'Smith'}) self._registerView(view, 'echo', IViewClassifier, rpc_iface, None) request_data = {'jsonrpc': '2.0', 'method': 'echo', 'id': 'echo-rpc', 'params':[13]} request = self._makeDummyRequest(request_data) response = self._callFUT(request) self.assertEqual(response.content_type, 'application/json') data = json.loads(response.body) self.assertEqual({"jsonrpc": "2.0", "id": "echo-rpc", "result": {'name': 'Smith'}}, data)
def test_jsonrpc_endpoint_internal_error(self): from pyramid_rpc.jsonrpc import JsonRpcInternalError from pyramid.interfaces import IViewClassifier view = DummyView(raise_exception=Exception) rpc_iface = self._registerRouteRequest('JSON-RPC') self._registerView(view, 'echo', IViewClassifier, rpc_iface, None) request_data = {'jsonrpc': '2.0', 'id': 'echo-rpc', 'method': 'echo', 'params':[13]} request = self._makeDummyRequest(request_data) response = self._callFUT(request) data = json.loads(response.body) self.assertEqual(data['error']['code'], JsonRpcInternalError.code)
def test_it_with_invalid_method(self): config = self.config config.include('pyramid_rpc.jsonrpc') config.add_jsonrpc_endpoint('rpc', '/api/jsonrpc') app = config.make_wsgi_app() app = TestApp(app) params = {'jsonrpc': '2.0', 'id': 5, 'method': 'foo', 'params': [2, 3]} resp = app.post('/api/jsonrpc', content_type='application/json', params=json.dumps(params)) self.assertEqual(resp.status_int, 200) self.assertEqual(resp.content_type, 'application/json') result = json.loads(resp.body) self.assertEqual(result['id'], 5) self.assertEqual(result['jsonrpc'], '2.0') self.assertEqual(result['error']['code'], -32601)
def test_jsonrpc_endpoint_invalid_response(self): from pyramid.interfaces import IViewClassifier from pyramid_rpc.jsonrpc import JsonRpcInternalError def invalid_view(context, request): return object() rpc_iface = self._registerRouteRequest('JSON-RPC') self._registerView(invalid_view, 'invalid', IViewClassifier, rpc_iface, None) request_data = {'jsonrpc': '2.0', 'id': 'invalid-rpc', 'method': 'invalid', 'params':[]} request = self._makeDummyRequest(request_data) response = self._callFUT(request) data = json.loads(response.body) self.assertEqual(data['error']['code'], JsonRpcInternalError.code)
def jsonrpc_endpoint(request): """A base view to be used with add_route to setup a JSON-RPC dispatch endpoint Use this view with ``add_route`` to setup a JSON-RPC endpoint, for example:: config.add_route('RPC2', '/apis/jsonrpc', view=jsonrpc_endpoint) JSON-RPC methods should then be registered with ``add_view`` using the route_name of the endpoint, the name as the jsonrpc method name. Or for brevity, the :class:`~pyramid_rpc.rpc_view` decorator can be used. For example, to register an jsonrpc method 'list_users':: @rpc_view() def list_users(request): json_params = request.rpc_args return {'users': [...]} Existing views that return a dict can be used with jsonrpc_view. """ length = request.content_length if length == 0: return jsonrpc_error_response(JsonRpcRequestInvalid()) try: body = json.loads(request.body) except ValueError: return jsonrpc_error_response(JsonRpcParseError()) if isinstance(body, dict): rpc_id = body.get('id') if body.get('jsonrpc') != '2.0': return jsonrpc_error_response(JsonRpcRequestInvalid(), rpc_id) if 'method' not in body: return jsonrpc_error_response(JsonRpcRequestInvalid(), rpc_id) try: data = _call_rpc(request, body) return jsonrpc_response(data, rpc_id) except Exception, e: if rpc_id is None: return Response(content_type="text/plain") return jsonrpc_error_response(e, rpc_id)
def index(self): def int_or_none(val): try: return int(val) except (TypeError, ValueError): return None offset = int_or_none(self.request.GET.get('offset')) limit = int_or_none(self.request.GET.get('limit')) query_spec = json.loads(self.request.GET.get('q', '{}')) resources = self.context.index(limit=limit, offset=offset, query_spec=query_spec) return { 'context': self.context, 'resources': resources, 'offset': offset, 'limit': limit }
def test_it_with_general_exception(self): def view(request): raise Exception() config = self.config config.include('pyramid_rpc.jsonrpc') config.add_jsonrpc_endpoint('rpc', '/api/jsonrpc') config.add_jsonrpc_method(view, endpoint='rpc', method='dummy') app = config.make_wsgi_app() app = TestApp(app) params = {'jsonrpc': '2.0', 'method': 'dummy', 'id': 5, 'params': [2, 3]} resp = app.post('/api/jsonrpc', content_type='application/json', params=json.dumps(params)) self.assertEqual(resp.status_int, 200) self.assertEqual(resp.content_type, 'application/json') result = json.loads(resp.body) self.assertEqual(result['id'], 5) self.assertEqual(result['jsonrpc'], '2.0') self.assertEqual(result['error']['code'], -32603)
def test_it_with_no_params(self): def view(request): self.assertEqual(request.rpc_args, []) return 'no params' config = self.config config.include('pyramid_rpc.jsonrpc') config.add_jsonrpc_endpoint('rpc', '/api/jsonrpc') config.add_jsonrpc_method(view, endpoint='rpc', method='dummy') app = config.make_wsgi_app() app = TestApp(app) params = {'jsonrpc': '2.0', 'id': 5, 'method': 'dummy'} resp = app.post('/api/jsonrpc', content_type='application/json', params=json.dumps(params)) self.assertEqual(resp.status_int, 200) self.assertEqual(resp.content_type, 'application/json') result = json.loads(resp.body) self.assertEqual(result['id'], 5) self.assertEqual(result['jsonrpc'], '2.0') self.assertEqual(result['result'], 'no params')
def _callFUT(self, app, method, params, id=5, version='2.0', path='/api/jsonrpc', content_type='application/json'): body = {} if id is not None: body['id'] = id if version is not None: body['jsonrpc'] = version if method is not None: body['method'] = method if params is not None: body['params'] = params resp = app.post(path, content_type=content_type, params=json.dumps(body)) self.assertEqual(resp.status_int, 200) self.assertEqual(resp.content_type, 'application/json') result = json.loads(resp.body) self.assertEqual(result['jsonrpc'], '2.0') self.assertEqual(result['id'], id) return result
def json_body(self): return json.loads(self.body, encoding=self.charset)
def process_result_value(self, value, dialect): if value is not None: value = json.loads(value) return value
def process_result_value(value, dialect): if value is not None: value = json.loads(value) return value
def json_body(self): return json.loads(text_(self.body, self.charset))
def json_body(self): return json.loads(self.body.decode(self.charset))
def default_decoder(request, body, charset): return json.loads(text_(body, charset))
def process_result_value(self, value, dialect): if value is not None: value = json.loads(value, object_hook=JSONDecoder()) return value
def test_decoder(request, str, charset): self.decoder_called = True return json.loads(str, charset)