Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parameter validator in connexion module expecting formData key which we never use in open api 3 #1340

Closed
vijaya2497 opened this issue Feb 10, 2021 · 1 comment · Fixed by #1374

Comments

@vijaya2497
Copy link

vijaya2497 commented Feb 10, 2021

Description

i am working on open api 3. For my PUT request content-type is set to multipart/form-data and also I have path parameter too. I enabled strict_validation for validating parameters. Parameter validator in connexion/decorators/validation.py is validating form parameters but in open api 3 we are not defining formData parameters like this( in:formData) anymore we are using request body only for media types.

def validate_formdata_parameter_list(self, request):
request_params = request.form.keys()

try:
    spec_params = [x['name'] for x in self.parameters['formData']]
except KeyError:
    # OAS 3
    return set()
return validate_parameter_list(request_params, spec_params)

we are using only in:path and in:query in openapi 3 so no need of checking for formData parameters in parameter validator class so my suggestion is to remove validate_formdata_parameter_list function from parameter validator

Expected behaviour

Actual behaviour

Steps to reproduce

Additional info:

Output of the commands:

  • python --version
  • pip show connexion | grep "^Version\:"
@vijaya2497 vijaya2497 changed the title python connexion module expecting formData key which we never use in open api 3 parameter validator in connexion module expecting formData key which we never use in open api 3 Jun 20, 2021
@vijaya2497
Copy link
Author

vijaya2497 commented Jun 20, 2021

class ParameterValidator(object):
def init(self, parameters, api, strict_validation=False):
"""
:param parameters: List of request parameter dictionaries
:param api: api that the validator is attached to
:param strict_validation: Flag indicating if parameters not in spec are allowed
"""
self.parameters = collections.defaultdict(list)
for p in parameters:
self.parameters[p['in']].append(p)

    self.api = api
    self.strict_validation = strict_validation

@staticmethod
def validate_parameter(parameter_type, value, param, param_name=None):
    if value is not None:
        if is_nullable(param) and is_null(value):
            return

        try:
            converted_value = coerce_type(param, value, parameter_type, param_name)
        except TypeValidationError as e:
            return str(e)

        param = copy.deepcopy(param)
        param = param.get('schema', param)
        if 'required' in param:
            del param['required']
        try:
            if parameter_type == 'formdata' and param.get('type') == 'file':
                if _jsonschema_3_or_newer:
                    extend(
                        Draft4Validator,
                        type_checker=Draft4Validator.TYPE_CHECKER.redefine(
                            "file",
                            lambda checker, instance: isinstance(instance, FileStorage)
                        )
                    )(param, format_checker=draft4_format_checker).validate(converted_value)
                else:
                    Draft4Validator(
                        param,
                        format_checker=draft4_format_checker,
                        types={'file': FileStorage}).validate(converted_value)
            else:
                Draft4Validator(
                    param, format_checker=draft4_format_checker).validate(converted_value)
        except ValidationError as exception:
            debug_msg = 'Error while converting value {converted_value} from param ' \
                        '{type_converted_value} of type real type {param_type} to the declared type {param}'
            fmt_params = dict(
                converted_value=str(converted_value),
                type_converted_value=type(converted_value),
                param_type=param.get('type'),
                param=param
            )
            logger.info(debug_msg.format(**fmt_params))
            return str(exception)

    elif param.get('required'):
        return "Missing {parameter_type} parameter '{param[name]}'".format(**locals())

def validate_query_parameter_list(self, request):
    request_params = request.query.keys()
    spec_params = [x['name'] for x in self.parameters.get('query', [])]
    return validate_parameter_list(request_params, spec_params)

**def validate_formdata_parameter_list(self, request):**
    request_params = request.form.keys()
    try:
        spec_params = [x['name'] for x in self.parameters['formData']]
    except KeyError:
        OAS 3
        return set()
    return validate_parameter_list(request_params, spec_params)**

def validate_query_parameter(self, param, request):
    """
    Validate a single query parameter (request.args in Flask)

    :type param: dict
    :rtype: str
    """
    val = request.query.get(param['name'])
    return self.validate_parameter('query', val, param)

def validate_path_parameter(self, param, request):
    val = request.path_params.get(param['name'].replace('-', '_'))
    return self.validate_parameter('path', val, param)

def validate_header_parameter(self, param, request):
    val = request.headers.get(param['name'])
    return self.validate_parameter('header', val, param)

def validate_cookie_parameter(self, param, request):
    val = request.cookies.get(param['name'])
    return self.validate_parameter('cookie', val, param)

def validate_formdata_parameter(self, param_name, param, request):
    if param.get('type') == 'file' or param.get('format') == 'binary':
        val = request.files.get(param_name)
    else:
        val = request.form.get(param_name)

    return self.validate_parameter('formdata', val, param)

def __call__(self, function):
    """
    :type function: types.FunctionType
    :rtype: types.FunctionType
    """

    @functools.wraps(function)
    def wrapper(request):
        logger.debug("%s validating parameters...", request.url)

        **if self.strict_validation:
            query_errors = self.validate_query_parameter_list(request)
            formdata_errors = self.validate_formdata_parameter_list(request)

            if query_errors and formdata_errors:
                raise ExtraParameterProblem(query_errors)**

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant