diff --git a/keystone/server/flask/common.py b/keystone/server/flask/common.py index 49a806913c..22d807d5b1 100644 --- a/keystone/server/flask/common.py +++ b/keystone/server/flask/common.py @@ -23,7 +23,9 @@ from flask import blueprints import flask_restful from oslo_log import log import six +from six.moves import http_client +from keystone.common import context from keystone.common import driver_hints from keystone.common import json_home from keystone.common.rbac_enforcer import enforcer @@ -136,6 +138,13 @@ def _assert_rbac_enforcement_called(resp): return resp +def _remove_content_type_on_204(resp): + # Remove content-type if the resp is 204. + if resp.status_code == http_client.NO_CONTENT: + resp.headers.pop('content-type', None) + return resp + + @six.add_metaclass(abc.ABCMeta) class APIBase(object): @@ -401,6 +410,7 @@ class APIBase(object): # register global after request functions # e.g. self.__blueprint.after_request(function) self.__blueprint.after_request(_assert_rbac_enforcement_called) + self.__blueprint.after_request(_remove_content_type_on_204) # Add Passed-In Functions for f in functions: @@ -582,6 +592,10 @@ class ResourceBase(flask_restful.Resource): return refs + @property + def oslo_context(self): + return flask.request.environ.get(context.REQUEST_CONTEXT_ENV, None) + @staticmethod def build_driver_hints(supported_filters): """Build list hints based on the context query string. @@ -669,6 +683,14 @@ class ResourceBase(flask_restful.Resource): return NOT_LIMITED, refs + @classmethod + def _normalize_dict(cls, d): + return {cls._normalize_arg(k): v for (k, v) in d.items()} + + @staticmethod + def _normalize_arg(arg): + return arg.replace(':', '_').replace('-', '_') + def base_url(): url = CONF['public_endpoint']