def on_error(self, state, e): if hasattr(e, 'body') and isinstance(e.body, dict): body = e.body else: body = {} if isinstance(e, exc.HTTPException): status_code = state.response.status message = str(e) elif isinstance(e, db_exceptions.StackStormDBObjectNotFoundError): status_code = httplib.NOT_FOUND message = str(e) elif isinstance(e, db_exceptions.StackStormDBObjectConflictError): status_code = httplib.CONFLICT message = str(e) body['conflict-id'] = e.conflict_id elif isinstance(e, rbac_exceptions.AccessDeniedError): status_code = httplib.FORBIDDEN message = str(e) elif isinstance(e, (ValueValidationException, ValueError)): status_code = httplib.BAD_REQUEST message = getattr(e, 'message', str(e)) else: status_code = httplib.INTERNAL_SERVER_ERROR message = 'Internal Server Error' # Log the error is_internal_server_error = status_code == httplib.INTERNAL_SERVER_ERROR error_msg = getattr(e, 'comment', str(e)) extra = { 'exception_class': e.__class__.__name__, 'exception_message': str(e), 'exception_data': e.__dict__ } if is_internal_server_error: LOG.exception('API call failed: %s', error_msg, extra=extra) LOG.exception(traceback.format_exc()) else: LOG.debug('API call failed: %s', error_msg, extra=extra) if is_debugging_enabled(): LOG.debug(traceback.format_exc()) body['faultstring'] = message response_body = json_encode(body) headers = state.response.headers or {} headers['Content-Type'] = 'application/json' headers['Content-Length'] = str(len(response_body)) return webob.Response(response_body, status=status_code, headers=headers)
def callfunction(*args, **kwargs): function_name = f.__name__ args = list(args) more = [args.pop(0)] def cast_value(value_type, value): if value_type == bool: def cast_func(value): return value.lower() in ['1', 'true'] else: cast_func = value_type result = cast_func(value) return result if body_cls: if pecan.request.body: data = pecan.request.json obj = body_cls(**data) try: obj = obj.validate() except (jsonschema.ValidationError, ValueError) as e: raise exc.HTTPBadRequest(detail=e.message, comment=traceback.format_exc()) except Exception as e: raise exc.HTTPInternalServerError(detail=e.message, comment=traceback.format_exc()) # Set default pack if one is not provided for resource create if function_name == 'post' and not hasattr(obj, 'pack'): extra = { 'resource_api': obj, 'default_pack_name': DEFAULT_PACK_NAME } LOG.debug('Pack not provided in the body, setting a default pack name', extra=extra) setattr(obj, 'pack', DEFAULT_PACK_NAME) else: obj = None more.append(obj) if arg_types: # Cast and transform arguments based on the provided arg_types specification result_args, result_kwargs = get_controller_args_for_types(func=f, arg_types=arg_types, args=args, kwargs=kwargs) more = more + result_args kwargs.update(result_kwargs) args = tuple(more) + tuple(args) noop_codes = [http_client.NOT_IMPLEMENTED, http_client.METHOD_NOT_ALLOWED, http_client.FORBIDDEN] if status_code and status_code in noop_codes: pecan.response.status = status_code return json_encode(None) try: result = f(*args, **kwargs) except TypeError as e: e = get_exception_for_type_error(func=f, exc=e) raise e if status_code: pecan.response.status = status_code if content_type == 'application/json': if is_debugging_enabled(): indent = 4 else: indent = None return json_encode(result, indent=indent) else: return result
def callfunction(*args, **kwargs): args = list(args) more = [args.pop(0)] def cast_value(value_type, value): if value_type == bool: def cast_func(value): return value.lower() in ['1', 'true'] else: cast_func = value_type result = cast_func(value) return result if body_cls: if pecan.request.body: data = pecan.request.json obj = body_cls(**data) try: obj = obj.validate() except (jsonschema.ValidationError, ValueError) as e: raise exc.HTTPBadRequest(detail=e.message, comment=traceback.format_exc()) except Exception as e: raise exc.HTTPInternalServerError(detail=e.message, comment=traceback.format_exc()) else: obj = None more.append(obj) if arg_types: # Cast and transform arguments based on the provided arg_types specification result_args, result_kwargs = get_controller_args_for_types(func=f, arg_types=arg_types, args=args, kwargs=kwargs) more = more + result_args kwargs.update(result_kwargs) args = tuple(more) + tuple(args) noop_codes = [http_client.NOT_IMPLEMENTED, http_client.METHOD_NOT_ALLOWED, http_client.FORBIDDEN] if status_code and status_code in noop_codes: pecan.response.status = status_code return json_encode(None) try: result = f(*args, **kwargs) except TypeError as e: e = get_exception_for_type_error(func=f, exc=e) raise e except Exception as e: e = get_exception_for_uncaught_api_error(func=f, exc=e) raise e if status_code: pecan.response.status = status_code if content_type == 'application/json': if is_debugging_enabled(): indent = 4 else: indent = None return json_encode(result, indent=indent) else: return result
def __call__(self, environ, start_response): # The middleware intercepts and handles all the errors happening down the call stack by # converting them to valid HTTP responses with semantically meaningful status codes and # predefined response structure (`{"faultstring": "..."}`). The earlier in the call stack is # going to be run, the less unhandled errors could slip to the wsgi layer. Keep in mind that # the middleware doesn't receive the headers that has been set down the call stack which # means that things like CorsMiddleware and RequestIDMiddleware should be highier up the # call stack to also apply to error responses. try: try: return self.app(environ, start_response) except NotFoundException: raise exc.HTTPNotFound() except Exception as e: status = getattr(e, "code", exc.HTTPInternalServerError.code) if hasattr(e, "detail") and not getattr(e, "comment"): setattr(e, "comment", getattr(e, "detail")) if hasattr(e, "body") and isinstance(getattr(e, "body", None), dict): body = getattr(e, "body", None) else: body = {} if isinstance(e, exc.HTTPException): status_code = status message = six.text_type(e) elif isinstance(e, db_exceptions.StackStormDBObjectNotFoundError): status_code = exc.HTTPNotFound.code message = six.text_type(e) elif isinstance(e, db_exceptions.StackStormDBObjectConflictError): status_code = exc.HTTPConflict.code message = six.text_type(e) body["conflict-id"] = getattr(e, "conflict_id", None) elif isinstance(e, rbac_exceptions.AccessDeniedError): status_code = exc.HTTPForbidden.code message = six.text_type(e) elif isinstance(e, (ValueValidationException, ValueError, ValidationError)): status_code = exc.HTTPBadRequest.code message = getattr(e, "message", six.text_type(e)) else: status_code = exc.HTTPInternalServerError.code message = "Internal Server Error" # Log the error is_internal_server_error = status_code == exc.HTTPInternalServerError.code error_msg = getattr(e, "comment", six.text_type(e)) extra = { "exception_class": e.__class__.__name__, "exception_message": six.text_type(e), "exception_data": e.__dict__, } if is_internal_server_error: LOG.exception("API call failed: %s", error_msg, extra=extra) else: LOG.debug("API call failed: %s", error_msg, extra=extra) if is_debugging_enabled(): LOG.debug(traceback.format_exc()) body["faultstring"] = message response_body = json_encode(body) headers = { "Content-Type": "application/json", # NOTE: We need to use the length of the byte string here otherwise it won't # work correctly when returning an unicode response - here we would measure number # of characters instead of actual byte length. # Another option would also be to not set it here and let webob set it when sending # the response. "Content-Length": str(len(response_body.encode("utf-8"))), } resp = Response(response_body, status=status_code, headers=headers) return resp(environ, start_response)
def __call__(self, environ, start_response): try: try: return self.app(environ, start_response) except NotFoundException: raise exc.HTTPNotFound() except Exception as e: status = getattr(e, 'code', exc.HTTPInternalServerError.code) if hasattr(e, 'detail') and not getattr(e, 'comment'): setattr(e, 'comment', getattr(e, 'detail')) if hasattr(e, 'body') and isinstance(getattr(e, 'body', None), dict): body = getattr(e, 'body', None) else: body = {} if isinstance(e, exc.HTTPException): status_code = status message = str(e) elif isinstance(e, db_exceptions.StackStormDBObjectNotFoundError): status_code = exc.HTTPNotFound.code message = str(e) elif isinstance(e, db_exceptions.StackStormDBObjectConflictError): status_code = exc.HTTPConflict.code message = str(e) body['conflict-id'] = getattr(e, 'conflict_id', None) elif isinstance(e, rbac_exceptions.AccessDeniedError): status_code = exc.HTTPForbidden.code message = str(e) elif isinstance(e, (ValueValidationException, ValueError, ValidationError)): status_code = exc.HTTPBadRequest.code message = getattr(e, 'message', str(e)) else: status_code = exc.HTTPInternalServerError.code message = 'Internal Server Error' # Log the error is_internal_server_error = status_code == exc.HTTPInternalServerError.code error_msg = getattr(e, 'comment', str(e)) extra = { 'exception_class': e.__class__.__name__, 'exception_message': str(e), 'exception_data': e.__dict__ } if is_internal_server_error: LOG.exception('API call failed: %s', error_msg, extra=extra) LOG.exception(traceback.format_exc()) else: LOG.debug('API call failed: %s', error_msg, extra=extra) if is_debugging_enabled(): LOG.debug(traceback.format_exc()) body['faultstring'] = message response_body = json_encode(body) headers = { 'Content-Type': 'application/json', 'Content-Length': str(len(response_body)) } resp = Response(response_body, status=status_code, headers=headers) return resp(environ, start_response)
def __call__(self, environ, start_response): # The middleware intercepts and handles all the errors happening down the call stack by # converting them to valid HTTP responses with semantically meaningful status codes and # predefined response structure (`{"faultstring": "..."}`). The earlier in the call stack is # going to be run, the less unhandled errors could slip to the wsgi layer. Keep in mind that # the middleware doesn't receive the headers that has been set down the call stack which # means that things like CorsMiddleware and RequestIDMiddleware should be highier up the # call stack to also apply to error responses. try: try: return self.app(environ, start_response) except NotFoundException: raise exc.HTTPNotFound() except Exception as e: status = getattr(e, 'code', exc.HTTPInternalServerError.code) if hasattr(e, 'detail') and not getattr(e, 'comment'): setattr(e, 'comment', getattr(e, 'detail')) if hasattr(e, 'body') and isinstance(getattr(e, 'body', None), dict): body = getattr(e, 'body', None) else: body = {} if isinstance(e, exc.HTTPException): status_code = status message = str(e) elif isinstance(e, db_exceptions.StackStormDBObjectNotFoundError): status_code = exc.HTTPNotFound.code message = str(e) elif isinstance(e, db_exceptions.StackStormDBObjectConflictError): status_code = exc.HTTPConflict.code message = str(e) body['conflict-id'] = getattr(e, 'conflict_id', None) elif isinstance(e, rbac_exceptions.AccessDeniedError): status_code = exc.HTTPForbidden.code message = str(e) elif isinstance( e, (ValueValidationException, ValueError, ValidationError)): status_code = exc.HTTPBadRequest.code message = getattr(e, 'message', str(e)) else: status_code = exc.HTTPInternalServerError.code message = 'Internal Server Error' # Log the error is_internal_server_error = status_code == exc.HTTPInternalServerError.code error_msg = getattr(e, 'comment', str(e)) extra = { 'exception_class': e.__class__.__name__, 'exception_message': str(e), 'exception_data': e.__dict__ } if is_internal_server_error: LOG.exception('API call failed: %s', error_msg, extra=extra) else: LOG.debug('API call failed: %s', error_msg, extra=extra) if is_debugging_enabled(): LOG.debug(traceback.format_exc()) body['faultstring'] = message response_body = json_encode(body) headers = { 'Content-Type': 'application/json', 'Content-Length': str(len(response_body)) } resp = Response(response_body, status=status_code, headers=headers) return resp(environ, start_response)
def callfunction(*args, **kwargs): function_name = f.__name__ args = list(args) more = [args.pop(0)] def cast_value(value_type, value): if value_type == bool: def cast_func(value): return value.lower() in ['1', 'true'] else: cast_func = value_type result = cast_func(value) return result if body_cls: if pecan.request.body: data = pecan.request.json obj = body_cls(**data) try: obj = obj.validate() except (jsonschema.ValidationError, ValueError) as e: raise exc.HTTPBadRequest( detail=e.message, comment=traceback.format_exc()) except Exception as e: raise exc.HTTPInternalServerError( detail=e.message, comment=traceback.format_exc()) # Set default pack if one is not provided for resource create if function_name == 'post' and not hasattr(obj, 'pack'): extra = { 'resource_api': obj, 'default_pack_name': DEFAULT_PACK_NAME } LOG.debug( 'Pack not provided in the body, setting a default pack name', extra=extra) setattr(obj, 'pack', DEFAULT_PACK_NAME) else: obj = None more.append(obj) if arg_types: # Cast and transform arguments based on the provided arg_types specification result_args, result_kwargs = get_controller_args_for_types( func=f, arg_types=arg_types, args=args, kwargs=kwargs) more = more + result_args kwargs.update(result_kwargs) args = tuple(more) + tuple(args) noop_codes = [ http_client.NOT_IMPLEMENTED, http_client.METHOD_NOT_ALLOWED, http_client.FORBIDDEN ] if status_code and status_code in noop_codes: pecan.response.status = status_code return json_encode(None) try: result = f(*args, **kwargs) except TypeError as e: e = get_exception_for_type_error(func=f, exc=e) raise e if status_code: pecan.response.status = status_code if content_type == 'application/json': if is_debugging_enabled(): indent = 4 else: indent = None return json_encode(result, indent=indent) else: return result
def callfunction(*args, **kwargs): function_name = f.__name__ args = list(args) types = copy.copy(arg_types) more = [args.pop(0)] if types: argspec = inspect.getargspec(f) names = argspec.args[1:] for name in names: try: a = args.pop(0) more.append(types.pop(0)(a)) except IndexError: try: kwargs[name] = types.pop(0)(kwargs[name]) except IndexError: LOG.warning("Type definition for '%s' argument of '%s' " "is missing.", name, f.__name__) except KeyError: pass if body_cls: if pecan.request.body: data = pecan.request.json else: data = {} obj = body_cls(**data) try: obj = obj.validate() except (jsonschema.ValidationError, ValueError) as e: raise exc.HTTPBadRequest(detail=e.message, comment=traceback.format_exc()) except Exception as e: raise exc.HTTPInternalServerError(detail=e.message, comment=traceback.format_exc()) # Set default pack if one is not provided for resource create if function_name == "post" and not hasattr(obj, "pack"): extra = {"resource_api": obj, "default_pack_name": DEFAULT_PACK_NAME} LOG.debug("Pack not provided in the body, setting a default pack name", extra=extra) setattr(obj, "pack", DEFAULT_PACK_NAME) more.append(obj) args = tuple(more) + tuple(args) noop_codes = [http_client.NOT_IMPLEMENTED, http_client.METHOD_NOT_ALLOWED, http_client.FORBIDDEN] if status_code and status_code in noop_codes: pecan.response.status = status_code return json_encode(None) try: result = f(*args, **kwargs) except TypeError as e: message = str(e) # Invalid number of arguments passed to the function meaning invalid path was # requested # Note: The check is hacky, but it works for now. func_name = f.__name__ pattern = "%s\(\) takes exactly \d+ arguments \(\d+ given\)" % (func_name) if re.search(pattern, message): raise exc.HTTPNotFound() else: raise e if status_code: pecan.response.status = status_code if content_type == "application/json": if is_debugging_enabled(): indent = 4 else: indent = None return json_encode(result, indent=indent) else: return result
def __call__(self, environ, start_response): # The middleware intercepts and handles all the errors happening down the call stack by # converting them to valid HTTP responses with semantically meaningful status codes and # predefined response structure (`{"faultstring": "..."}`). The earlier in the call stack is # going to be run, the less unhandled errors could slip to the wsgi layer. Keep in mind that # the middleware doesn't receive the headers that has been set down the call stack which # means that things like CorsMiddleware and RequestIDMiddleware should be highier up the # call stack to also apply to error responses. try: try: return self.app(environ, start_response) except NotFoundException: raise exc.HTTPNotFound() except Exception as e: status = getattr(e, 'code', exc.HTTPInternalServerError.code) if hasattr(e, 'detail') and not getattr(e, 'comment'): setattr(e, 'comment', getattr(e, 'detail')) if hasattr(e, 'body') and isinstance(getattr(e, 'body', None), dict): body = getattr(e, 'body', None) else: body = {} if isinstance(e, exc.HTTPException): status_code = status message = six.text_type(e) elif isinstance(e, db_exceptions.StackStormDBObjectNotFoundError): status_code = exc.HTTPNotFound.code message = six.text_type(e) elif isinstance(e, db_exceptions.StackStormDBObjectConflictError): status_code = exc.HTTPConflict.code message = six.text_type(e) body['conflict-id'] = getattr(e, 'conflict_id', None) elif isinstance(e, rbac_exceptions.AccessDeniedError): status_code = exc.HTTPForbidden.code message = six.text_type(e) elif isinstance(e, (ValueValidationException, ValueError, ValidationError)): status_code = exc.HTTPBadRequest.code message = getattr(e, 'message', six.text_type(e)) else: status_code = exc.HTTPInternalServerError.code message = 'Internal Server Error' # Log the error is_internal_server_error = status_code == exc.HTTPInternalServerError.code error_msg = getattr(e, 'comment', six.text_type(e)) extra = { 'exception_class': e.__class__.__name__, 'exception_message': six.text_type(e), 'exception_data': e.__dict__ } if is_internal_server_error: LOG.exception('API call failed: %s', error_msg, extra=extra) else: LOG.debug('API call failed: %s', error_msg, extra=extra) if is_debugging_enabled(): LOG.debug(traceback.format_exc()) body['faultstring'] = message response_body = json_encode(body) headers = { 'Content-Type': 'application/json', 'Content-Length': str(len(response_body)) } resp = Response(response_body, status=status_code, headers=headers) return resp(environ, start_response)
def callfunction(*args, **kwargs): function_name = f.__name__ args = list(args) types = copy.copy(arg_types) more = [args.pop(0)] if types: argspec = inspect.getargspec(f) names = argspec.args[1:] for name in names: try: a = args.pop(0) more.append(types.pop(0)(a)) except IndexError: try: kwargs[name] = types.pop(0)(kwargs[name]) except IndexError: LOG.warning( "Type definition for '%s' argument of '%s' " "is missing.", name, f.__name__) except KeyError: pass if body_cls: if pecan.request.body: data = pecan.request.json else: data = {} obj = body_cls(**data) try: obj = obj.validate() except (jsonschema.ValidationError, ValueError) as e: raise exc.HTTPBadRequest(detail=e.message, comment=traceback.format_exc()) except Exception as e: raise exc.HTTPInternalServerError( detail=e.message, comment=traceback.format_exc()) # Set default pack if one is not provided for resource create if function_name == 'post' and not hasattr(obj, 'pack'): extra = { 'resource_api': obj, 'default_pack_name': DEFAULT_PACK_NAME } LOG.debug( 'Pack not provided in the body, setting a default pack name', extra=extra) setattr(obj, 'pack', DEFAULT_PACK_NAME) more.append(obj) args = tuple(more) + tuple(args) noop_codes = [ http_client.NOT_IMPLEMENTED, http_client.METHOD_NOT_ALLOWED, http_client.FORBIDDEN ] if status_code and status_code in noop_codes: pecan.response.status = status_code return json_encode(None) try: result = f(*args, **kwargs) except TypeError as e: message = str(e) # Invalid number of arguments passed to the function meaning invalid path was # requested # Note: The check is hacky, but it works for now. func_name = f.__name__ pattern = '%s\(\) takes exactly \d+ arguments \(\d+ given\)' % ( func_name) if re.search(pattern, message): raise exc.HTTPNotFound() else: raise e if status_code: pecan.response.status = status_code if content_type == 'application/json': if is_debugging_enabled(): indent = 4 else: indent = None return json_encode(result, indent=indent) else: return result