diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 7c32b0b..6f9613a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -4,7 +4,7 @@ on: [pull_request] jobs: pre-commit: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2e21641..ee69f72 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: rev: 24.4.2 hooks: - id: black - language_version: python3.8 + language_version: python3.11 args: - --target-version=py38 - --line-length=120 diff --git a/CHANGELOG.md b/CHANGELOG.md index b9ac3ca..ca3d51f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Changelog ========= +3.5.1 +----- +- Fix payload loading issue when content type header contains but not exactly "application/json" + + 3.5.0 ----- - [feature] add `NUMBER` that accepts float and integer diff --git a/data_spec_validator/__version__.py b/data_spec_validator/__version__.py index 01bd03c..bf5afe7 100644 --- a/data_spec_validator/__version__.py +++ b/data_spec_validator/__version__.py @@ -1 +1 @@ -__version__ = '3.5.0' +__version__ = '3.5.1' diff --git a/data_spec_validator/decorator/decorators.py b/data_spec_validator/decorator/decorators.py index 25d5446..73bd7c2 100644 --- a/data_spec_validator/decorator/decorators.py +++ b/data_spec_validator/decorator/decorators.py @@ -104,8 +104,7 @@ def _collect_data(method, req_qp, req_data) -> Dict: return req_data def _get_dj_payload(request): - content_type = request.headers.get('Content-Type') - if content_type == 'application/json': + if request.content_type and 'application/json' in request.content_type: try: return request.body and json.loads(request.body) or {} except Exception: diff --git a/test/utils.py b/test/utils.py index eeb75aa..3f06484 100644 --- a/test/utils.py +++ b/test/utils.py @@ -43,11 +43,36 @@ def make_request(cls, path='/', method='GET', user=None, headers=None, data=None kwargs = {'REQUEST_METHOD': method, 'PATH_INFO': path, 'wsgi.input': StringIO()} if qs: kwargs.update({'QUERY_STRING': qs}) + + # Set content type in initial environ if data is provided + if data and method in ['POST', 'PUT', 'PATCH', 'DELETE']: + kwargs.update( + { + 'CONTENT_TYPE': 'application/json' if is_json else 'application/x-www-form-urlencoded', + 'CONTENT_LENGTH': len(str(data)), + } + ) + req = WSGIRequest(kwargs) else: kwargs = {'path': path, 'method': method} if qs: kwargs.update({'query_string': qs}) + + # Set content type in initial scope if data is provided + if data and method in ['POST', 'PUT', 'PATCH', 'DELETE']: + headers = kwargs.get('headers', []) + headers.extend( + [ + [ + b'content-type', + ('application/json' if is_json else 'application/x-www-form-urlencoded').encode(), + ], + [b'content-length', str(len(str(data))).encode()], + ] + ) + kwargs['headers'] = headers + req = ASGIRequest(kwargs, StringIO()) req.user = user @@ -60,12 +85,6 @@ def make_request(cls, path='/', method='GET', user=None, headers=None, data=None setattr(req, 'GET', data) elif method in ['POST', 'PUT', 'PATCH', 'DELETE']: req.read() # trigger RawPostDataException and force DRF to load data from req.POST - req.META.update( - { - 'CONTENT_TYPE': 'application/json' if is_json else 'application/x-www-form-urlencoded', - 'CONTENT_LENGTH': len(str(data)), - } - ) if is_json: req._body = data req.POST = {}