summaryrefslogtreecommitdiffstats
path: root/keystone
diff options
context:
space:
mode:
Diffstat (limited to 'keystone')
-rw-r--r--keystone/backends/ldap/__init__.py (renamed from keystone/queryext/__init__.py)0
-rw-r--r--keystone/middleware/url.py84
-rw-r--r--keystone/queryext/exthandler.py67
-rwxr-xr-xkeystone/server.py29
-rw-r--r--keystone/test/run_tests.py3
-rwxr-xr-xkeystone/test/unit/test_keystone.py2
-rw-r--r--keystone/test/unit/test_urlrewritefilter.py (renamed from keystone/test/unit/test_exthandler.py)31
-rwxr-xr-xkeystone/utils.py19
8 files changed, 120 insertions, 115 deletions
diff --git a/keystone/queryext/__init__.py b/keystone/backends/ldap/__init__.py
index e69de29b..e69de29b 100644
--- a/keystone/queryext/__init__.py
+++ b/keystone/backends/ldap/__init__.py
diff --git a/keystone/middleware/url.py b/keystone/middleware/url.py
new file mode 100644
index 00000000..3c876b8c
--- /dev/null
+++ b/keystone/middleware/url.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright (c) 2010 OpenStack, LLC.
+#
+# 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.
+
+
+"""
+Auth Middleware that accepts URL query extension.
+
+This module can be installed as a filter in front of your service to
+detect extension in the resource URI (e.g., foo/resource.xml) to
+specify HTTP response body type. If an extension is specified, it
+overwrites the Accept header in the request, if present.
+
+"""
+
+CONTENT_TYPES = {'json': 'application/json', 'xml': 'application/xml'}
+DEFAULT_CONTENT_TYPE = CONTENT_TYPES['json']
+
+class UrlRewriteFilter(object):
+ """Middleware filter to handle URL rewriting"""
+
+ def __init__(self, app, conf):
+ # app is the next app in WSGI chain - eventually the OpenStack service
+ self.app = app
+ self.conf = conf
+
+ def __call__(self, env, start_response):
+ (env['PATH_INFO'], env['HTTP_ACCEPT']) = self.override_accept_header(
+ env.get('PATH_INFO'), env.get('HTTP_ACCEPT'))
+
+ env['PATH_INFO'] = self.remove_trailing_slash(env.get('PATH_INFO'))
+
+ return self.app(env, start_response)
+
+ def override_accept_header(self, path_info, http_accept):
+ """Looks for an (.json/.xml) extension on the URL, removes it, and
+ overrides the Accept header if an extension was found"""
+ # try to split the extension from the rest of the path
+ parts = path_info.rsplit('.', 1)
+ if len(parts) > 1:
+ (path, ext) = parts
+ else:
+ (path, ext) = (parts[0], None)
+
+ if ext in CONTENT_TYPES:
+ # Use the content type specified by the extension
+ return (path, CONTENT_TYPES[ext])
+ elif http_accept is None or http_accept == '*/*':
+ # TODO: This probably isn't the best place to handle "Accept: */*"
+ # No extension or Accept header specified, use default
+ return (path_info, DEFAULT_CONTENT_TYPE)
+ else:
+ # Return what we were given
+ return (path_info, http_accept)
+
+ def remove_trailing_slash(self, path_info):
+ """Removes a trailing slash from the given path, if any"""
+ if path_info[-1] == '/':
+ return path_info[:-1]
+ else:
+ return path_info
+
+def filter_factory(global_conf, **local_conf):
+ """Returns a WSGI filter app for use with paste.deploy."""
+ conf = global_conf.copy()
+ conf.update(local_conf)
+
+ def ext_filter(app):
+ return UrlRewriteFilter(app, conf)
+ return ext_filter
diff --git a/keystone/queryext/exthandler.py b/keystone/queryext/exthandler.py
deleted file mode 100644
index cedf26fa..00000000
--- a/keystone/queryext/exthandler.py
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/env python
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-#
-# Copyright (c) 2010 OpenStack, LLC.
-#
-# 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.
-
-
-"""
-Auth Middleware that accepts URL query extension.
-
-This module can be installed as a filter in front of your service to
-detect extension in the resource URI (e.g., foo/resource.xml) to
-specify HTTP response body type. If an extension is specified, it
-overwrites the Accept header in the request, if present.
-
-"""
-
-
-# Does this need to be configurable?
-DEFAULT_EXTS = {'xml': 'application/xml', 'json': 'application/json'}
-
-
-def scrub(uri, ext):
- urisegs = uri.split('?')
- first = urisegs[0][0: -(len(ext) + 1)]
- if len(urisegs) > 1:
- return '?'.join((first, urisegs[1], ))
- else:
- return first
-
-
-class UrlExtensionFilter(object):
-
- def __init__(self, app, conf):
- # app is the next app in WSGI chain - eventually the OpenStack service
- self.app = app
- self.conf = conf
-
- print 'Starting extension handler middleware'
-
- def __call__(self, env, start_response):
- uri = env['PATH_INFO']
- querysegs = uri.split('?')
- ressegs = querysegs[0].split('.')
- if len(ressegs) > 1: # (Maybe) has an extension
- ext = ressegs[-1]
- if ext in DEFAULT_EXTS:
- env['HTTP_ACCEPT'] = DEFAULT_EXTS[ext]
- scrubbed = querysegs[0][0: -(len(ext) + 1)] # Remove extension
- if len(querysegs) > 1: # Has query string
- env['PATH_INFO'] = '?'.join((scrubbed, querysegs[1], ))
- else:
- env['PATH_INFO'] = scrubbed
-
- return self.app(env, start_response)
diff --git a/keystone/server.py b/keystone/server.py
index 79ed98af..56cb4482 100755
--- a/keystone/server.py
+++ b/keystone/server.py
@@ -509,27 +509,18 @@ def get_marker_limit_and_url(req):
if "limit" in req.GET:
limit = req.GET["limit"]
+
url = get_url(req)
+
return (marker, limit, url)
-def get_marker_and_limit(req):
- marker = None
- limit = 10
-
- if "marker" in req.GET:
- marker = req.GET["marker"]
-
- if "limit" in req.GET:
- limit = req.GET["limit"]
-
-
def get_url(req):
- url = '%s://%s:%s%s' % (req.environ['wsgi.url_scheme'],
- req.environ.get("SERVER_NAME"),
- req.environ.get("SERVER_PORT"),
- req.environ['PATH_INFO'])
- return url
+ return '%s://%s:%s%s' % (
+ req.environ['wsgi.url_scheme'],
+ req.environ.get("SERVER_NAME"),
+ req.environ.get("SERVER_PORT"),
+ req.environ['PATH_INFO'])
class KeystoneAPI(wsgi.Router):
@@ -552,9 +543,6 @@ class KeystoneAPI(wsgi.Router):
# Miscellaneous Operations
version_controller = VersionController(options)
- mapper.connect("/v2.0/", controller=version_controller,
- action="get_version_info",
- conditions=dict(method=["GET"]))
mapper.connect("/v2.0", controller=version_controller,
action="get_version_info",
conditions=dict(method=["GET"]))
@@ -764,9 +752,6 @@ class KeystoneAdminAPI(wsgi.Router):
# Miscellaneous Operations
version_controller = VersionController(options)
- mapper.connect("/v2.0/", controller=version_controller,
- action="get_version_info",
- conditions=dict(method=["GET"]))
mapper.connect("/v2.0", controller=version_controller,
action="get_version_info",
conditions=dict(method=["GET"]))
diff --git a/keystone/test/run_tests.py b/keystone/test/run_tests.py
index 190f632d..15fb8ede 100644
--- a/keystone/test/run_tests.py
+++ b/keystone/test/run_tests.py
@@ -1,4 +1,5 @@
import os
+import sys
import subprocess
import time
@@ -20,7 +21,7 @@ if __name__ == '__main__':
# blatent hack.
time.sleep(3)
if server.poll() is not None:
- print >>sys.stderr, 'Failed to start server'
+ print >> sys.stderr, 'Failed to start server'
sys.exit(-1)
try:
diff --git a/keystone/test/unit/test_keystone.py b/keystone/test/unit/test_keystone.py
index 05fe1864..5909c08f 100755
--- a/keystone/test/unit/test_keystone.py
+++ b/keystone/test/unit/test_keystone.py
@@ -9,7 +9,7 @@ TEST_FILES = [
#'test_authn_v2.py', # this is largely failing
'test_common.py', # this doesn't actually contain tests
'test_endpoints.py',
- 'test_exthandler.py',
+ 'test_urlrewritefilter.py',
'test_groups.py',
'test_keystone.py', # not sure why this is referencing itself
'test_roles.py',
diff --git a/keystone/test/unit/test_exthandler.py b/keystone/test/unit/test_urlrewritefilter.py
index 30a61f98..e22c362f 100644
--- a/keystone/test/unit/test_exthandler.py
+++ b/keystone/test/unit/test_urlrewritefilter.py
@@ -14,13 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import os
-import sys
-# Need to access identity module
-sys.path.append(os.path.abspath(os.path.join(
- os.getcwd(), '..', '..', 'keystone')))
-from keystone.queryext.exthandler import UrlExtensionFilter
+
import unittest
+from keystone.middleware.url import UrlRewriteFilter
class MockWsgiApp(object):
@@ -39,7 +35,23 @@ def _start_response():
class UrlExtensionFilterTest(unittest.TestCase):
def setUp(self):
- self.filter = UrlExtensionFilter(MockWsgiApp(), {})
+ self.filter = UrlRewriteFilter(MockWsgiApp(), {})
+
+ def test_remove_trailing_slash(self):
+ env = {'PATH_INFO': '/v2.0/'}
+ self.filter(env, _start_response)
+ self.assertEqual('/v2.0', env['PATH_INFO'])
+
+ def test_remove_trailing_slash_from_empty_path(self):
+ env = {'PATH_INFO': '/'}
+ self.filter(env, _start_response)
+ self.assertEqual('', env['PATH_INFO'])
+
+ def test_no_extension(self):
+ env = {'PATH_INFO': '/v2.0/someresource'}
+ self.filter(env, _start_response)
+ self.assertEqual('/v2.0/someresource', env['PATH_INFO'])
+ self.assertEqual('application/json', env['HTTP_ACCEPT'])
def test_xml_extension(self):
env = {'PATH_INFO': '/v2.0/someresource.xml'}
@@ -54,8 +66,9 @@ class UrlExtensionFilterTest(unittest.TestCase):
self.assertEqual('application/json', env['HTTP_ACCEPT'])
def test_extension_overrides_header(self):
- env = {'PATH_INFO': '/v2.0/someresource.json',
- 'HTTP_ACCEPT': 'application/xml'}
+ env = {
+ 'PATH_INFO': '/v2.0/someresource.json',
+ 'HTTP_ACCEPT': 'application/xml'}
self.filter(env, _start_response)
self.assertEqual('/v2.0/someresource', env['PATH_INFO'])
self.assertEqual('application/json', env['HTTP_ACCEPT'])
diff --git a/keystone/utils.py b/keystone/utils.py
index ddd63760..96991364 100755
--- a/keystone/utils.py
+++ b/keystone/utils.py
@@ -16,19 +16,10 @@
import functools
-import httplib
-import json
import logging
import os
-import routes
import sys
-import hashlib
from webob import Response
-from webob import Request
-from webob import descriptors
-from webob.exc import (HTTPNotFound,
- HTTPConflict,
- HTTPBadRequest)
POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,
@@ -36,14 +27,12 @@ POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'keystone', '__init__.py')):
sys.path.insert(0, POSSIBLE_TOPDIR)
-from queryext import exthandler
import keystone.logic.types.fault as fault
def is_xml_response(req):
- if not "Accept" in req.headers:
- return False
- return req.content_type == "application/xml"
+ """Returns True when the request wants an XML response, False otherwise"""
+ return "Accept" in req.headers and "application/xml" in req.accept
def get_app_root():
@@ -180,5 +169,5 @@ def import_module(module_name, class_name=None):
__import__(module_name)
return getattr(sys.modules[module_name], class_name)
except (ImportError, ValueError, AttributeError), exception:
- raise ImportError(_('Class %s.%s cannot be found (%s)') %
- (module_name, class_name, exception)) \ No newline at end of file
+ raise ImportError(_('Class %s.%s cannot be found (%s)') %
+ (module_name, class_name, exception))