예제 #1
0
파일: hooks.py 프로젝트: yangjiebeijing/st2
    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)
예제 #2
0
파일: hooks.py 프로젝트: Pulsant/st2
    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)
예제 #3
0
파일: base.py 프로젝트: maniacs-ops/st2
        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
예제 #4
0
파일: base.py 프로젝트: yuemanxilou/st2
        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
예제 #5
0
파일: base.py 프로젝트: LindsayHill/st2
        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
예제 #6
0
    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)
예제 #7
0
    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)
예제 #8
0
    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)
예제 #9
0
        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
예제 #10
0
파일: base.py 프로젝트: ojosdegris/st2
        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
예제 #11
0
    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)
예제 #12
0
        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