Skip to content

ResponseValidator: how to handle mime-type with character encoding details? #378

Closed
@erikbos

Description

@erikbos

While using ResponseValidator.validate I noticed validation is sensitive to the content-type header including character encoding details.

In case an HTTP response includes content-type: application/json; charset=utf-8 validation fails: MediaTypeNotFound(mimetype='application/json; charset=utf-8', availableMimetypes=['application/json'])

(As quick work I tried adding application/json; charset=utf-8 to the openapi spec as additional mime-type but that results in vague errors such as raised in #128)

I can manually overwrite mimetype of the response before validating but that feels a bit wrong .. one could reason that application/json; charset=utf-8 should be accepted and treated equal as application/json. Any comment?

See below for code that reproduces this situation.

import json
from openapi_core import create_spec
from openapi_core.validation.request.validators import RequestValidator
from openapi_core.validation.response.validators import ResponseValidator
from openapi_core.testing import MockRequest
from openapi_core.testing import MockResponse

def validate(spec_dict, mime_type):
    spec = create_spec(spec_dict)

    openapi_request = MockRequest('localhost', 'get', '/v1/cars')
    validator = RequestValidator(spec)
    result = validator.validate(openapi_request)
    request_errors = result.errors

    data = json.dumps({
        'cars' :[
            {
                'name': 'car1',
            },
            {
                'name': 'car2',
            }
        ]
    })
    openapi_response = MockResponse(data, mimetype=mime_type)

    # Workaround
    #if openapi_response.mimetype == 'application/json; charset=utf-8':
    #     openapi_response.mimetype = 'application/json'

    validator = ResponseValidator(spec)
    result = validator.validate(openapi_request, openapi_response)
    response_errors = result.errors

    print('Request errors: {} Response errors: {}'.format(request_errors, response_errors))


spec = {
    'openapi': '3.0.0',
    'info': {
        'version': '0.1',
        'title': 'List of objects',
        'description': 'Test for list of objects'
    },
    'paths': {
        '/v1/cars': {
            'get': {
                'description': 'Retrieve all cars',
                'responses': {
                    '200': {
                        'description': 'Successfully retrieved all cars',
                        'content': {
                            'application/json': {
                                'schema': {
                                    'type': 'object',
                                    'properties': {
                                        'cars': {
                                            'type': 'array',
                                            'items': {
                                                '$ref': '#/components/schemas/Car'
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    'components': {
        'schemas': {
            'Car': {
                'type': 'object',
                'properties': {
                    'name': {
                        'type': 'string'
                    }
                }
            }
        }
    }
}
validate(spec, 'application/json')
validate(spec, 'application/json; charset=utf-8')

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions