# keystone.server.flask.request_processing.json_body

# Source code for keystone.server.flask.request_processing.json_body

    # Licensed under the Apache License, Version 2.0 (the "License"); you may
    # not use this file except in compliance with the License. You may obtain
    # a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    # License for the specific language governing permissions and limitations
    # under the License.

    # Before request processing for JSON Body enforcement

    import flask
    from werkzeug import exceptions as werkzeug_exceptions

    from keystone import exception
    from keystone.i18n import _
    from keystone.server.flask import common as ks_flask_common

    def json_body_before_request():
        """Enforce JSON Request Body."""
        # TODO(morgan): Allow other content-types when OpenAPI Doc or improved
        # federation is implemented for known/valid paths. This function should
        # be removed long term.

        # exit if there is nothing to be done, (no body)
        if not flask.request.get_data():
            return None
        elif flask.request.path and flask.request.path.startswith(
            '/v3/OS-OAUTH2/'
        ):
            # When the user makes a request to the OAuth2.0 token endpoint,
            # the user should use the "application/x-www-form-urlencoded" format
            # with a character encoding of UTF-8 in the HTTP request entity-body.
            # At the scenario there is nothing to be done and exit.
            return None

        try:
            # flask does loading for us for json, use the flask default loader
            # in the case that the data is *not* json or a dict, we should see a
            # raise of werkzeug.exceptions.BadRequest, re-spin this to the keystone
            # ValidationError message (as expected by our contract)

            # Explicitly check if the content is supposed to be json.
            if (
                flask.request.is_json
                or flask.request.headers.get('Content-Type', '') == ''
            ):
                json_decoded = flask.request.get_json(force=True)
                if not isinstance(json_decoded, dict):
                    # In the case that the returned value was not a dict, force
                    # a raise that will be caught the same way that a Decode error
                    # would be handled.
                    raise werkzeug_exceptions.BadRequest(
                        _('resulting JSON load was not a dict')
                    )
            else:
                # We no longer need enforcement on this API, set unenforced_ok
                # we already hit a validation error. This is required as the
                # request is never hitting the resource methods, meaning
                # @unenforced_api is not called. Without marking the request
                # as "unenforced_ok" the assertion check to ensure enforcement
                # was called would raise up causing a 500 error.
                ks_flask_common.set_unenforced_ok()
                raise exception.ValidationError(
                    attribute='application/json', target='Content-Type header'
                )

        except werkzeug_exceptions.BadRequest:
            # We no longer need enforcement on this API, set unenforced_ok
            # we already hit a validation error. This is required as the
            # request is never hitting the resource methods, meaning
            # @unenforced_api is not called. Without marking the request
            # as "unenforced_ok" the assertion check to ensure enforcement
            # was called would raise up causing a 500 error.
            ks_flask_common.set_unenforced_ok()
            raise exception.ValidationError(
                attribute='valid JSON', target='request body'
            )

this page last updated: 2026-04-01 20:09:17

Except where otherwise noted, this document is licensed under Creative Commons Attribution 3.0 License. See all OpenStack Legal Documents.

found an error? report a bug