diff options
| author | Gordon Chung <chungg@ca.ibm.com> | 2013-02-21 15:52:12 -0500 |
|---|---|---|
| committer | Gordon Chung <chungg@ca.ibm.com> | 2013-03-07 17:06:38 -0500 |
| commit | dd7d4fd551f727873462d3ef2ece863ab6400995 (patch) | |
| tree | 67032fdfcd41e89ef63b5541c116f22055ab5990 | |
| parent | 2b49a0ad13a4aca086474f101b104ac562e1f2f0 (diff) | |
return 201 Created on POST request (bug1131119)
correct status code from 200 Ok to 201 Created for v3 POST requests.
Fixes: bug #1131119
Change-Id: Iabeb6daf677e0f34defdef5e58d87229fc90346f
| -rw-r--r-- | keystone/auth/controllers.py | 4 | ||||
| -rw-r--r-- | keystone/auth/token_factory.py | 9 | ||||
| -rw-r--r-- | keystone/common/wsgi.py | 13 | ||||
| -rw-r--r-- | tests/test_content_types.py | 2 | ||||
| -rw-r--r-- | tests/test_v3.py | 30 |
5 files changed, 45 insertions, 13 deletions
diff --git a/keystone/auth/controllers.py b/keystone/auth/controllers.py index 96f3dc0c..ec532b1b 100644 --- a/keystone/auth/controllers.py +++ b/keystone/auth/controllers.py @@ -294,8 +294,8 @@ class Auth(controller.V3Controller): auth_context) (token_id, token_data) = token_factory.create_token( context, auth_context, auth_info) - return token_factory.render_token_data_response(token_id, - token_data) + return token_factory.render_token_data_response( + token_id, token_data, created=True) except (exception.Unauthorized, exception.AuthMethodNotSupported, exception.AdditionalAuthRequired) as e: diff --git a/keystone/auth/token_factory.py b/keystone/auth/token_factory.py index 8460aec6..4d5c0b87 100644 --- a/keystone/auth/token_factory.py +++ b/keystone/auth/token_factory.py @@ -294,7 +294,7 @@ def create_token(context, auth_context, auth_info): return (token_id, token_data) -def render_token_data_response(token_id, token_data): +def render_token_data_response(token_id, token_data, created=False): """ Render token data HTTP response. Stash token ID into the X-Auth-Token header. @@ -303,7 +303,12 @@ def render_token_data_response(token_id, token_data): headers = [('X-Subject-Token', token_id)] headers.append(('Vary', 'X-Auth-Token')) headers.append(('Content-Type', 'application/json')) - status = (200, 'OK') + + if created: + status = (201, 'Created') + else: + status = (200, 'OK') + body = jsonutils.dumps(token_data, cls=utils.SmarterEncoder) return webob.Response(body=body, status='%s %s' % status, diff --git a/keystone/common/wsgi.py b/keystone/common/wsgi.py index 108cc0ca..672a82f3 100644 --- a/keystone/common/wsgi.py +++ b/keystone/common/wsgi.py @@ -33,6 +33,7 @@ from keystone.common import logging from keystone.common import utils from keystone import config from keystone import exception +from keystone.openstack.common import importutils from keystone.openstack.common import jsonutils @@ -251,7 +252,17 @@ class Application(BaseApplication): return result elif isinstance(result, webob.exc.WSGIHTTPException): return result - return render_response(body=result) + + response_code = self._get_response_code(req) + return render_response(body=result, status=response_code) + + def _get_response_code(self, req): + req_method = req.environ['REQUEST_METHOD'] + controller = importutils.import_class('keystone.common.controller') + code = None + if isinstance(self, controller.V3Controller) and req_method == 'POST': + code = (201, 'Created') + return code def _normalize_arg(self, arg): return str(arg).replace(':', '_').replace('-', '_') diff --git a/tests/test_content_types.py b/tests/test_content_types.py index e0b42db9..a5457ccb 100644 --- a/tests/test_content_types.py +++ b/tests/test_content_types.py @@ -373,7 +373,6 @@ class CoreApiTests(object): 'tenantId': self.tenant_bar['id'], }, }, - # TODO(dolph): creating a token should result in a 201 Created expected_status=200) self.assertValidAuthenticationResponse(r) @@ -389,7 +388,6 @@ class CoreApiTests(object): }, }, }, - # TODO(dolph): creating a token should result in a 201 Created expected_status=200) self.assertValidAuthenticationResponse(r) diff --git a/tests/test_v3.py b/tests/test_v3.py index 39807cec..9b4f7d34 100644 --- a/tests/test_v3.py +++ b/tests/test_v3.py @@ -221,22 +221,40 @@ class RestfulTestCase(test_content_types.RestfulTestCase): **kwargs) def get(self, path, **kwargs): - return self.v3_request(method='GET', path=path, **kwargs) + r = self.v3_request(method='GET', path=path, **kwargs) + if 'expected_status' not in kwargs: + self.assertResponseStatus(r, 200) + return r def head(self, path, **kwargs): - return self.v3_request(method='HEAD', path=path, **kwargs) + r = self.v3_request(method='HEAD', path=path, **kwargs) + if 'expected_status' not in kwargs: + self.assertResponseStatus(r, 204) + return r def post(self, path, **kwargs): - return self.v3_request(method='POST', path=path, **kwargs) + r = self.v3_request(method='POST', path=path, **kwargs) + if 'expected_status' not in kwargs: + self.assertResponseStatus(r, 201) + return r def put(self, path, **kwargs): - return self.v3_request(method='PUT', path=path, **kwargs) + r = self.v3_request(method='PUT', path=path, **kwargs) + if 'expected_status' not in kwargs: + self.assertResponseStatus(r, 204) + return r def patch(self, path, **kwargs): - return self.v3_request(method='PATCH', path=path, **kwargs) + r = self.v3_request(method='PATCH', path=path, **kwargs) + if 'expected_status' not in kwargs: + self.assertResponseStatus(r, 200) + return r def delete(self, path, **kwargs): - return self.v3_request(method='DELETE', path=path, **kwargs) + r = self.v3_request(method='DELETE', path=path, **kwargs) + if 'expected_status' not in kwargs: + self.assertResponseStatus(r, 204) + return r def assertValidErrorResponse(self, r): if r.getheader('Content-Type') == 'application/xml': |
