def moya_render(self, archive, context, target, options): template = [options.get('template', None)] style = options.get('style', None) or self.style template.append(self.get_template_path(style, self.fieldname)) if style is not 'simple': template.append(self.get_template_path('simple', self.fieldname)) r = RenderContainer.create(archive.find_app('moya.forms'), template=template) r['self'] = self r['field'] = self if self.data is not None: r.update(self.data) return r.moya_render(archive, context, target, options)
def run(self, context): """Generate a response for either a GET or a POST""" request = context['.request'] app = context.get('.app', None) interface_id = "<interface {}#{}>".format(app.name, self.libname) if request.method == "GET": render_container = RenderContainer.create(app, template="moya.jsonrpc/interface.html") render_container['interface'] = self context['_return'] = render_container return if request.method != "POST": return context['.jsonrpc'] = {"request": {}} try: req = json.loads(request.body.decode('utf-8')) except Exception as e: log.debug("%s badly formatted JSONRPC request: %s", interface_id, e) response = self.make_error(None, False, code=ErrorCode.parse_error, message=text_type(e)) raise logic.EndLogic(response) batch = isinstance(req, list) responses = [] for response in self.process_request(context, req): if response is None: # Notification continue elif isinstance(response, ErrorResponse): # Problem with request responses.append(response) elif isinstance(response, CallMethod): # Request good, do call method, params, req_id, notification = response log.debug("%s %s '%s' with %s", interface_id, 'notify' if notification else 'call', method.name, lazystr(to_expression, context, params, 80)) try: params = response.method.process_params(params) except ParamError as e: response = ErrorResponse(ErrorCode.invalid_params, text_type(e), id=req_id) self.log_result(context, response) responses.append(response) continue def do_call(element, app, params): try: return_value = self.archive.call(element.libid, context, app, **params) except Exception as e: if isinstance(e.original, MoyaException): moya_exc = e.original if moya_exc.type == "jsonrpc.error": return RPCErrorReturn(moya_exc.info['code'], moya_exc.info['message'], moya_exc.info['data']) error_message = "exception '{}' in rpc call to {}".format(e, method) if hasattr(e, 'moya_trace'): log.error(error_message) if context['.debug'] and context['.console']: context['.console'].obj(context, e) else: error_message = "{}\n{}".format(error_message, e.moya_trace) log.error(error_message) else: context['.console'].obj(context, e) log.exception(error_message) response = ErrorResponse(ErrorCode.internal_error, 'internal error -- this error has been logged', id=req_id) return response else: return return_value return_value = do_call(method.element, app, params) if method.macro is not None and not isinstance(return_value, (RPCResponse, RPCErrorReturn)): try: macro_app, macro_element = self.get_element(method.macro, app) except Exception as e: log.error("%s no macro called '%s'", interface_id, method.macro) return_value = ErrorResponse(ErrorCode.internal_error, "internal error -- this error has been logged", id=req_id) else: return_value = do_call(macro_element, app, params) if isinstance(return_value, RPCResponse): self.log_result(context, return_value) responses.append(return_value) continue if notification: continue if isinstance(return_value, RPCErrorReturn): code, message, data = return_value if code.isdigit(): code = int(code) else: try: code = int(self.errors[code]) if not message: message = self.errors[code].description except Exception as e: log.error("invalid error code '{}' -- defaulting to 'internal_error'".format(code)) code = ErrorCode.internal_error message = ErrorCode.to_str[code] return_value = RPCErrorReturn(code, message, data) response = ErrorResponse(code, message, data=data, id=req_id) self.log_result(context, response) else: # Check the response is serializable try: moyajson.dumps(return_value) except Exception as e: log.error(text_type(e)) response = ErrorResponse(ErrorCode.internal_error, 'internal error -- server was unable to serialize the response', id=req_id) self.log_result(context, response) else: response = SuccessResponse(return_value, req_id) self.log_result(context, return_value) responses.append(response) if not responses: raise logic.EndLogic(Response(content_type=b'application/json' if PY2 else 'application/json')) try: if batch: response_json = moyajson.dumps(responses, indent=4) else: response_json = moyajson.dumps(responses[0], indent=4) except Exception as e: log.exception("error serializing response") error_response = ErrorResponse(ErrorCode.internal_error, "server was unable to generate a response -- this error has been logged", id=None) response_json = moyajson.dumps(error_response) response = Response(content_type=b'application/json' if PY2 else 'application/json', body=response_json) raise logic.EndLogic(response) yield # Because this method should be a generator
def run(self, context): """Generate a response for either a GET or a POST""" request = context[".request"] app = context.get(".app", None) interface_id = "<interface {}#{}>".format(app.name, self.libname) if request.method == "GET": render_container = RenderContainer.create( app, template="moya.jsonrpc/interface.html") render_container["interface"] = self context["_return"] = render_container return if request.method != "POST": return context[".jsonrpc"] = {"request": {}} try: req = json.loads(request.body.decode("utf-8")) except Exception as e: log.debug("%s badly formatted JSONRPC request: %s", interface_id, e) response = self.make_error(None, False, code=ErrorCode.parse_error, message=text_type(e)) raise logic.EndLogic(response) batch = isinstance(req, list) responses = [] for response in self.process_request(context, req): if response is None: # Notification continue elif isinstance(response, ErrorResponse): # Problem with request responses.append(response) elif isinstance(response, CallMethod): # Request good, do call method, params, req_id, notification = response log.debug( "%s %s '%s' with %s", interface_id, "notify" if notification else "call", method.name, lazystr(to_expression, context, params, 80), ) try: params = response.method.process_params(context, params) except ParamError as e: response = ErrorResponse(ErrorCode.invalid_params, text_type(e), id=req_id) self.log_result(context, response) responses.append(response) continue def do_call(element, app, params): try: return_value = self.archive.call( element.libid, context, app, **params) except Exception as e: if isinstance(getattr(e, "original", None), MoyaException): moya_exc = e.original if moya_exc.type == "jsonrpc.error": return RPCErrorReturn( moya_exc.info["code"], moya_exc.info["message"], moya_exc.info["data"], ) error_message = "exception '{}' in rpc call to {}".format( e, method) if hasattr(e, "moya_trace"): log.error(error_message) if context[".debug"] and context[".console"]: context[".console"].obj(context, e) else: error_message = "{}\n{}".format( error_message, e.moya_trace) log.error(error_message) else: context[".console"].obj(context, e) log.exception(error_message) response = ErrorResponse( ErrorCode.internal_error, "internal error -- this error has been logged", id=req_id, ) return response else: return return_value return_value = do_call(method.element, app, params) if method.macro is not None and not isinstance( return_value, (RPCResponse, RPCErrorReturn)): try: macro_app, macro_element = self.get_element( method.macro, app) except Exception as e: log.error("%s no macro called '%s'", interface_id, method.macro) return_value = ErrorResponse( ErrorCode.internal_error, "internal error -- this error has been logged", id=req_id, ) else: return_value = do_call(macro_element, app, params) if isinstance(return_value, RPCResponse): self.log_result(context, return_value) responses.append(return_value) continue if notification: continue if isinstance(return_value, RPCErrorReturn): code, message, data = return_value if code.isdigit(): code = int(code) else: try: code = int(self.errors[code]) if not message: message = self.errors[code].description except Exception as e: log.error( "invalid error code '{}' -- defaulting to 'internal_error'" .format(code)) code = ErrorCode.internal_error message = ErrorCode.to_str[code] return_value = RPCErrorReturn(code, message, data) response = ErrorResponse(code, message, data=data, id=req_id) self.log_result(context, response) else: # Check the response is serializable try: moyajson.dumps(return_value) except Exception as e: log.error(text_type(e)) response = ErrorResponse( ErrorCode.internal_error, "internal error -- server was unable to serialize the response", id=req_id, ) self.log_result(context, response) else: response = SuccessResponse(return_value, req_id) self.log_result(context, return_value) responses.append(response) if not responses: raise logic.EndLogic( Response(content_type=b"application/json" if PY2 else "application/json")) try: if batch: response_json = moyajson.dumps(responses, indent=4) else: response_json = moyajson.dumps(responses[0], indent=4) except Exception as e: log.exception("error serializing response") error_response = ErrorResponse( ErrorCode.internal_error, "server was unable to generate a response -- this error has been logged", id=None, ) response_json = moyajson.dumps(error_response) response = Response( content_type=b"application/json" if PY2 else "application/json", body=response_json, ) raise logic.EndLogic(response) yield # Because this method should be a generator