コード例 #1
0
ファイル: accepts.py プロジェクト: anhducc13/flask-api
    def decorator(func):
        from functools import wraps

        @wraps(func)
        def inner(*args, **kwargs):
            from flask import request
            user = None
            if authorization:
                bearer_token = request.headers.get('Authorization')
                if bearer_token and len(bearer_token.split(' ')) == 2:
                    token = bearer_token.split(' ')[1]
                    user = AuthorizationUtils.get_user_info(token)
                    request.user_extra = user
                else:
                    raise ErrorTokenException

            if permissions is not None and isinstance(permissions, List):
                if user and user.role and user.role.has_all_permissions:
                    return func(*args, **kwargs)
                user_permissions = []
                if user and user.permissions:
                    user_permissions = user.permissions
                accept = all([(item in user_permissions)
                              for item in permissions])
                if not accept:
                    raise NotPermissionException
            if schema:
                if has_request_params:
                    try:
                        obj = schema.load(request.args)
                        request.parse_args = obj
                    except ValidationError:
                        raise PhysicalValidationException(
                            message='The query param is not valid')

                else:
                    try:
                        obj = schema.load(request.get_json())
                        request.parse_obj = obj
                    except ValidationError as err:
                        raise PhysicalValidationException(extra=err.messages)

            return func(*args, **kwargs)

        if api and use_swagger:
            if schema:
                inner = api.doc(
                    params={qp["name"]: qp
                            for qp in query_params},
                    body=for_swagger(
                        schema=schema,
                        model_name=get_default_model_name(schema),
                        api=api,
                        operation="load",
                    ),
                )(inner)
            elif _parser:
                inner = api.expect(_parser)(inner)
        return inner
コード例 #2
0
    def decorator(func):
        from functools import wraps

        # Check if we are decorating a class method
        _IS_METHOD = _is_method(func)

        @wraps(func)
        def inner(*args, **kwargs):
            from flask import request

            error = schema_error = None
            # Handle arguments
            try:
                request.parsed_args = _parser.parse_args()
            except Exception as e:
                error = e

            # Handle Marshmallow schema
            if schema:
                try:
                    obj = schema.load(request.get_json())
                    request.parsed_obj = obj
                except ValidationError as ex:
                    schema_error = ex.messages
                if schema_error:
                    error = error or BadRequest(
                        f"Invalid parsing error: {schema_error}")
                    if hasattr(error, "data"):
                        error.data["errors"].update(
                            {"schema_errors": schema_error})
                    else:
                        error.data = {"schema_errors": schema_error}

            # If any parsing produced an error, combine them and re-raise
            if error:
                raise error

            return func(*args, **kwargs)

        # Add Swagger
        if api and use_swagger and _IS_METHOD:
            if schema:
                inner = api.doc(
                    params={qp["name"]: qp
                            for qp in query_params},
                    body=for_swagger(
                        schema=schema,
                        model_name=model_name
                        or get_default_model_name(schema),
                        api=api,
                        operation="load",
                    ),
                )(inner)
            elif _parser:
                inner = api.expect(_parser)(inner)
        return inner
コード例 #3
0
def responds(
    *args,
    model_name: str = None,
    schema=None,
    many: bool = False,
    api=None,
    envelope=None,
    status_code: int = 200,
    validate: bool = False,
    description: str = None,
    use_swagger: bool = True,
):
    """
    Serialize the output of a function using the Marshmallow schema to dump the results.
    Note that `schema` should be the type, not an instance -- the `responds` decorator
    will internally handle creation of the schema. If the outputted value is already of
    type flask.Response, it will be passed along without further modification.

    Args:
        schema (bool, optional): Marshmallow schema with which to serialize the output
            of the wrapped function.
        many (bool, optional): (DEPRECATED) The Marshmallow schema `many` parameter, which will
            return a list of the corresponding schema objects when set to True.

    Returns:
        The output of schema(many=many).dumps(<return value>) of the wrapped function
    """
    from functools import wraps

    from flask_restx import reqparse

    _check_deprecate_many(many)

    # If an api was passed in, we need to use its parser so Swagger is aware
    if api:
        _parser = api.parser()
    else:
        _parser = reqparse.RequestParser(bundle_errors=True)

    query_params = [arg for arg in args if isinstance(arg, dict)]

    for arg in args:  # check for positional string-arg, which is the model name
        if isinstance(arg, str):
            model_name = arg
            break
    for qp in query_params:
        _parser.add_argument(**qp, location="values")

    ordered = None
    if schema:
        schema = _get_or_create_schema(schema, many=many)
        ordered = schema.ordered

    model_name = model_name or get_default_model_name(schema)
    model_from_parser = _model_from_parser(model_name=model_name,
                                           parser=_parser)

    def decorator(func):

        # Check if we are decorating a class method
        _IS_METHOD = _is_method(func)

        @wraps(func)
        def inner(*args, **kwargs):
            rv = func(*args, **kwargs)

            # If a Flask response has been made already, it is passed through unchanged
            if isinstance(rv, Response):
                return rv
            if schema:
                serialized = schema.dump(rv)

                # Validate data if asked to (throws)
                if validate:
                    errs = schema.validate(serialized)
                    if errs:
                        raise InternalServerError(
                            description=
                            "Server attempted to return invalid data")

                # Apply the flask-restx mask after validation
                serialized = _apply_restx_mask(serialized)
            else:
                from flask_restx import marshal

                serialized = marshal(rv, model_from_parser)

            if envelope:
                serialized = OrderedDict([(envelope,
                                           serialized)]) if ordered else {
                                               envelope: serialized
                                           }

            if not _is_method(func):
                # Regular route, need to manually create Response
                return jsonify(serialized), status_code
            return serialized, status_code

        # Add Swagger
        if api and use_swagger and _IS_METHOD:
            if schema:
                api_model = for_swagger(schema=schema,
                                        model_name=model_name,
                                        api=api,
                                        operation="dump")
                if schema.many is True:
                    api_model = [api_model]

                inner = _document_like_marshal_with(
                    api_model,
                    status_code=status_code,
                    description=description,
                )(inner)

            elif _parser:
                api.add_model(model_name, model_from_parser)
                inner = _document_like_marshal_with(
                    model_from_parser, status_code=status_code)(inner)

        return inner

    return decorator
コード例 #4
0
    def decorator(func):
        from functools import wraps

        # Check if we are decorating a class method
        _IS_METHOD = _is_method(func)

        @wraps(func)
        def inner(*args, **kwargs):
            from flask import request

            error = schema_error = None

            # Handle arguments
            try:
                request.parsed_args = _parser.parse_args()
            except Exception as e:
                error = e

            # Handle Marshmallow schema for request body
            if schema:
                try:
                    obj = schema.load(request.get_json())
                    request.parsed_obj = obj
                except ValidationError as ex:
                    schema_error = ex.messages
                if schema_error:
                    error = error or BadRequest(
                        f"Error parsing request body: {schema_error}")
                    if hasattr(error, "data"):
                        error.data["errors"].update(
                            {"schema_errors": schema_error})
                    else:
                        error.data = {"schema_errors": schema_error}

            # Handle Marshmallow schema for query params
            if query_params_schema:
                request_args = _convert_multidict_values_to_schema(
                    request.args, query_params_schema)

                try:
                    obj = query_params_schema.load(request_args)
                    request.parsed_query_params = obj
                except ValidationError as ex:
                    schema_error = ex.messages
                if schema_error:
                    error = error or BadRequest(
                        f"Error parsing query params: {schema_error}")
                    if hasattr(error, "data"):
                        error.data["errors"].update(
                            {"schema_errors": schema_error})
                    else:
                        error.data = {"schema_errors": schema_error}

            # Handle Marshmallow schema for headers
            if headers_schema:
                request_headers = _convert_multidict_values_to_schema(
                    request.headers, headers_schema)

                try:
                    obj = headers_schema.load(request_headers)
                    request.parsed_headers = obj
                except ValidationError as ex:
                    schema_error = ex.messages
                if schema_error:
                    error = error or BadRequest(
                        f"Error parsing headers: {schema_error}")
                    if hasattr(error, "data"):
                        error.data["errors"].update(
                            {"schema_errors": schema_error})
                    else:
                        error.data = {"schema_errors": schema_error}

            # If any parsing produced an error, combine them and re-raise
            if error:
                raise error

            return func(*args, **kwargs)

        # Add Swagger
        if api and use_swagger and _IS_METHOD:
            if schema:
                body = for_swagger(
                    schema=schema,
                    model_name=model_name or get_default_model_name(schema),
                    api=api,
                    operation="load",
                )
                params = {
                    "expect": [body, _parser],
                }
                inner = api.doc(**params)(inner)
            elif _parser:
                inner = api.expect(_parser)(inner)
        return inner
コード例 #5
0
ファイル: decorators.py プロジェクト: weiztech/flask_accepts
    def decorator(func):
        from functools import wraps

        # Check if we are decorating a class method
        _IS_METHOD = _is_method(func)

        @wraps(func)
        def inner(*args, **kwargs):
            from flask import request

            error = schema_error = None

            # Handle arguments
            try:
                request.parsed_args = _parser.parse_args()
            except Exception as e:
                error = e

            # Handle Marshmallow schema for request body
            if schema:
                try:
                    headers = request.headers.get('content-type', '')
                    # allow parsing multipart/form-data and x-www-form-urlencoded
                    if 'form' in headers:
                        data = {**request.form}
                        # convert form data with value string of dict/list to object dict/list
                        for key, value in data.items():
                            if isinstance(value, str) and value.strip():
                                try:
                                    data[key] = literal_eval(value)
                                except (ValueError, SyntaxError):
                                    pass
                        # add files to data
                        data.update(request.files)
                    else:
                        data = request.get_json(force=True)

                    obj = schema.load(data)
                    request.parsed_obj = obj
                except ValidationError as ex:
                    schema_error = ex.messages
                if schema_error:
                    error = error or BadRequest(
                        f"Error parsing request body: {schema_error}")
                    if hasattr(error, "data"):
                        error.data["errors"].update(
                            {"schema_errors": schema_error})
                    else:
                        error.data = {"schema_errors": schema_error}

            # Handle Marshmallow schema for query params
            if query_params_schema:
                request_args = _convert_multidict_values_to_schema(
                    request.args, query_params_schema)

                try:
                    obj = query_params_schema.load(request_args)
                    request.parsed_query_params = obj
                except ValidationError as ex:
                    schema_error = ex.messages
                if schema_error:
                    error = error or BadRequest(
                        f"Error parsing query params: {schema_error}")
                    if hasattr(error, "data"):
                        error.data["errors"].update(
                            {"schema_errors": schema_error})
                    else:
                        error.data = {"schema_errors": schema_error}

            # Handle Marshmallow schema for headers
            if headers_schema:
                request_headers = _convert_multidict_values_to_schema(
                    request.headers, headers_schema)

                try:
                    obj = headers_schema.load(request_headers)
                    request.parsed_headers = obj
                except ValidationError as ex:
                    schema_error = ex.messages
                if schema_error:
                    error = error or BadRequest(
                        f"Error parsing headers: {schema_error}")
                    if hasattr(error, "data"):
                        error.data["errors"].update(
                            {"schema_errors": schema_error})
                    else:
                        error.data = {"schema_errors": schema_error}

            # If any parsing produced an error, combine them and re-raise
            if error:
                raise error

            return func(*args, **kwargs)

        # Add Swagger
        if api and use_swagger and _IS_METHOD:
            if schema:
                body = for_swagger(
                    schema=schema,
                    model_name=model_name or get_default_model_name(schema),
                    api=api,
                    operation="load",
                )
                if schema.many is True:
                    body = [body]

                params = {
                    "expect": [body, _parser],
                }
                inner = api.doc(**params)(inner)
            elif _parser:
                inner = api.expect(_parser)(inner)
        return inner