[Repoze-checkins] r793 - in repoze.vhm/trunk: . repoze/vhm repoze/vhm/tests
Chris McDonough
chrism at agendaless.com
Mon Mar 10 04:41:49 UTC 2008
Author: Chris McDonough <chrism at agendaless.com>
Date: Sun Mar 9 23:41:49 2008
New Revision: 793
Log:
Kill off path-segment-based filter (repoze.vhm.zope2). Only the
xheaders filter remains.
Add license headers.
The middleware now sets a 'repoze.vhm.virtual_host_base' which is
preferred by setServerUrl over 'HTTP_HOST' when present.
Add a getVirtualRoot API.
Added:
repoze.vhm/trunk/repoze/vhm/middleware.py (contents, props changed)
repoze.vhm/trunk/repoze/vhm/tests/test_middleware.py (contents, props changed)
repoze.vhm/trunk/repoze/vhm/tests/test_utils.py (contents, props changed)
repoze.vhm/trunk/repoze/vhm/utils.py (contents, props changed)
Removed:
repoze.vhm/trunk/repoze/vhm/tests/test_xheaders.py
repoze.vhm/trunk/repoze/vhm/tests/test_zope2.py
repoze.vhm/trunk/repoze/vhm/xheaders.py
repoze.vhm/trunk/repoze/vhm/zope2.py
Modified:
repoze.vhm/trunk/CHANGES.txt
repoze.vhm/trunk/README.txt
repoze.vhm/trunk/repoze/vhm/__init__.py
repoze.vhm/trunk/repoze/vhm/constants.py
repoze.vhm/trunk/setup.py
Modified: repoze.vhm/trunk/CHANGES.txt
==============================================================================
--- repoze.vhm/trunk/CHANGES.txt (original)
+++ repoze.vhm/trunk/CHANGES.txt Sun Mar 9 23:41:49 2008
@@ -1,3 +1,15 @@
+0.4 (2008-03-09)
+
+ Kill off path-segment-based filter (repoze.vhm.zope2). Only the
+ xheaders filter remains.
+
+ Add license headers.
+
+ The middleware now sets a 'repoze.vhm.virtual_host_base' which is
+ preferred by setServerUrl over 'HTTP_HOST' when present.
+
+ Add a getVirtualRoot API.
+
0.3
Fix setServerURL method to take into account HTTP_HOST passed by
Modified: repoze.vhm/trunk/README.txt
==============================================================================
--- repoze.vhm/trunk/README.txt (original)
+++ repoze.vhm/trunk/README.txt Sun Mar 9 23:41:49 2008
@@ -2,13 +2,12 @@
Overview
- This package provides some glue for doing Zope2-style virtual hosting
- within the 'repoze.zope2' environment, where the classic Zope2
+ This package provides middleware and utilities for doing virtual
+ hosting within a WSGI/Repoze environment. It is particularly
+ useful within a 'repoze.zope2' environment, where it may be used
+ as an alternative to the classic
"VirtualHostMonster":http://www.zope.org/Members/4am/SiteAccess2/info
- won't work.
-
- It also provides CGI-environment-munging middleware that is
- potentially useful within a non-Zope WSGI application.
+ method of doing virtual hosting.
Virtual Hosting in a Nutshell
@@ -32,7 +31,9 @@
'mod_python'), there follwing environment variables are of interest
when doing virtual hosting:
- 'SERVER_NAME' -- the apparent hostname of the server (i.e., as
+ 'SERVER_NAME' -- the name which the server believes it has.
+
+ 'HTTP_HOST' -- the apparent hostname of the server (i.e., as
passed in the 'Host:' header)
'SERVER_PORT' -- the apparent port of the server
@@ -43,37 +44,29 @@
'PATH_INFO' -- the remainder of the path, after removing any parts
used in dispatch.
- Zope2 Virtual Hosting Model
-
- In scenarios which use Apache rewrite + proxy to host a Zope application
- "behind" Apache, the classic Zope recipe is to rewrite the URL, adding
- virtual hosting information as extra path elements, which are then
- consumed during traversal of the Zope root by the VHM. E.g., the
- Apache server might see a request like:
-
- http://www.example.com/news/politics/local/mayor_impeached.html
-
- And rewrite it onto the Zope backend as something like:
-
- http://localhost:8080/VirtualHostBase/http/www.example.com:80/cms/VirtualHostRoot/news/politics/local/mayor_impeached.html
-
- The VHM would then transform the request, re-converting the path into:
+ 'repoze.vhm#xheaders' WSGI Filter
- /cms/news/politics/local/mayor_impeached.html
+ When configured as WSGI middleware, theis filter will convert the
+ path information in the environment from the "X-Vhm" headers added
+ to the request into the "standard" CGI environment variables
+ outlined above. It will also place repoze.vhm-specific
+ environment variables into the WSGI environment for consumption by
+ repoze.zope2 (or another application which chooses to use its
+ services).
+
+ If this filter is placed into the pipeline in front of a Zope 2
+ application, the standard Virtual Host Monster object
+ ('/virtual_hosting') may be deleted, as it is no longer necessary.
+ However, it does not need to be deleted; repoze.vhm will work if
+ it is present.
- setting the "virtual root" of the request to the '/cms' object,
- and also setting the 'SERVER_URL' in the request to:
+ The filter requires no configuration; it can be added to any
+ pipeline via its egg name: "egg:repoze.vhm#vhm_xheaders".
- http://www.example.com/
+ repoze.vhm Virtual Hosting Model
- Zope3 Virtual Hosting Model
-
- TODO: show the example using Z3's syntax.
-
- Proxy Headers Virtual Hosting Model
-
- This model, based on a "suggestion of Ian Bicking's",
- http://blog.ianbicking.org/2007/08/10/defaults-inheritance/ ,
+ This model (based on a "suggestion of Ian Bicking's",
+ http://blog.ianbicking.org/2007/08/10/defaults-inheritance/),
passes virtual hosting information from the proxy / web server to
the application by adding extra headers to the proxied request:
@@ -85,44 +78,64 @@
'HTTP_X_VHM_ROOT' -- path of the object within the application
which is supposed to function as the "virtual root".
- When serving an application from "within" Apache, we can just set
- the environment directly::
+ When serving an application from "within" Apache via mod_wsgi, we
+ can just set the environment directly::
<Directory /path/to/wsgiapp>
- SetEnv HTTP_X_VHM_HOST http://www.example.com/
- SetEnv HTTP_X_VHM_ROOT /cms
+ SetEnv HTTP_X_VHM_HOST http://www.example.com/
+ SetEnv HTTP_X_VHM_ROOT /cms
</Directory>
- Proxies pass this information by adding additional headers. E.g.,
- a sample Apache configuration for the example above might be::
+ If you are serving repoze.zope2 via a proxy rewrite rule, you may
+ pass this information by adding additional headers. E.g., a
+ sample Apache configuration for the example above might be::
<VirtualHost *:80>
ServerName www.example.com
RewriteEngine on
- RewriteRule ^/(.*) http://localhost:8080/$1
+ RewriteRule ^/(.*) http://localhost:8080/$1 [P,L]
Header add X-VHm-Host http://www.example.com/
Header add X-VHm-Root /cms
</VirtualHost>
- 'repoze.vhm' WSGI Filters
+ In either of the above example cases, the effect on repoze.zope2
+ when repoze.vhm's filter is in the WSGI pipeline is the same: the
+ apparent root of "http://www.example.com" will be the default view
+ of the object that has a physical path of "/cms". Additionally,
+ paths in URLs generated by Zope will not start with '/cms', and
+ the scheme and hostname in URLs will be "http://www.example.com"
+ as opposed to "http://localhost:8080".
+
+ The "vhm host" header may contain further path information as
+ necessary; further path information can (and will, in the case of
+ repoze.zope2) be respected by downstream applications to root an
+ application at a non-server-root path ::
+
+ <Directory /path/to/wsgiapp>
+ SetEnv HTTP_X_VHM_HOST http://www.example.com/further/path
+ SetEnv HTTP_X_VHM_ROOT /cms
+ </Directory>
- This package provides two filters for use in the "behind" (proxied)
- scenario described above, one for each model. When configured as
- WSGI middleware, these filters convert the path information in the
- environment from the Zope-specific syntax into the "standard" CGI
- environment variables outlined above.
+ In this case, URLs generated by Zope will begin with
+ "http://www.example.com/further/path". This syntax replaces the
+ "inside out" virtual hosting syntax ('_vh_' segment markers in the
+ URL) as described in the "Virtual Host Monster" documentation.
+
+ The "vhm host" and "vhm root" headers can be used independently
+ (the system will operate as you would expect in the absence of one
+ or the other).
'repoze.vhm' Library API
- Because the existing Zope virtual hosting solutions do not rely
- on the "standard" CGI variables, the application dispatcher needs to
- "fix up" the environment to match Zope's expectations. 'repoze.vhm'
- offers the following functions to aid in this fixup:
+ Because the existing Zope 2 virtual hosting machinery does not
+ rely on the "standard" CGI variables, the application dispatcher
+ needs to "fix up" the environment to match Zope's expectations.
+ 'repoze.vhm' offers the following functions to aid in this fixup:
- 'repoze.vhm.zope2.setServerURL' -- convert the standard CGI
+ 'repoze.vhm.utils.setServerURL' -- convert the standard CGI
virtual hosting environment into the form expected by Zope2
(adding the 'SERVER_URL' key).
- 'repoze.vhm.zope2.setVirtualRoot' -- mark the object serving
- as the virtual root for the current Zope2 request. (TODO)
+ 'repoze.vhm.utils.getVirtualRoot' -- return the virtual root
+ path ('repoze.vhm.virtual_root') as set by the middleware.
Modified: repoze.vhm/trunk/repoze/vhm/__init__.py
==============================================================================
--- repoze.vhm/trunk/repoze/vhm/__init__.py (original)
+++ repoze.vhm/trunk/repoze/vhm/__init__.py Sun Mar 9 23:41:49 2008
@@ -1,15 +1,2 @@
# repoze virtual hosting WSGI middleware
-class VHM_Z3:
- def __init__(self, application):
- self.application = application
-
- def __call__(self, environ, start_response):
- # TODO: Consume VHM-style tokens from environ['PATH_INFO'] and stash
- # them away in the format expected by Zope3's vhosting.
- result = self.application(environ, start_response)
- return result
-
-def make_vhm_z3(app, global_conf):
- return VHM_Z3(app)
-
Modified: repoze.vhm/trunk/repoze/vhm/constants.py
==============================================================================
--- repoze.vhm/trunk/repoze/vhm/constants.py (original)
+++ repoze.vhm/trunk/repoze/vhm/constants.py Sun Mar 9 23:41:49 2008
@@ -1,3 +1,17 @@
+##############################################################################
+#
+# Copyright (c) 2008 Agendaless Consulting and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the BSD-like license at
+# http://www.repoze.org/LICENSE.txt. A copy of the license should accompany
+# this distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL
+# EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND
+# FITNESS FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
DEFAULT_PORTS = {'http': '80',
Added: repoze.vhm/trunk/repoze/vhm/middleware.py
==============================================================================
--- (empty file)
+++ repoze.vhm/trunk/repoze/vhm/middleware.py Sun Mar 9 23:41:49 2008
@@ -0,0 +1,56 @@
+##############################################################################
+#
+# Copyright (c) 2008 Agendaless Consulting and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the BSD-like license at
+# http://www.repoze.org/LICENSE.txt. A copy of the license should accompany
+# this distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL
+# EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND
+# FITNESS FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+from urlparse import urlsplit
+
+from repoze.vhm.constants import DEFAULT_PORTS
+
+class VHMFilter:
+ """ WSGI ingress filter:
+
+ o Converts HTTP header-based vhost info into "stock" CGI
+ equivalents, with extra keys in the 'repoze.vhm' namespace.
+
+ o After conversion, the environment should be suitable for munging
+ via 'utils.setServerURL' (for compatibility with OFS.Traversable).
+ """
+ def __init__(self, application):
+ self.application = application
+
+ def __call__(self, environ, start_response):
+
+ host_header = environ.get('HTTP_X_VHM_HOST')
+
+ if host_header is not None:
+ (scheme, netloc, path, query, fragment) = urlsplit(host_header)
+ if ':' in netloc:
+ host, port = netloc.split(':')
+ else:
+ host = netloc
+ port = DEFAULT_PORTS[scheme]
+ environ['wsgi.url_scheme'] = scheme
+ environ['SERVER_NAME'] = host
+ environ['SERVER_PORT'] = port
+ environ['SCRIPT_NAME'] = path
+ environ['repoze.vhm.virtual_host_base'] = '%s:%s' % (host, port)
+
+ root_header = environ.get('HTTP_X_VHM_ROOT')
+
+ if root_header is not None:
+ environ['repoze.vhm.virtual_root'] = root_header
+
+ return self.application(environ, start_response)
+
+def make_filter(app, global_conf):
+ return VHMFilter(app)
Added: repoze.vhm/trunk/repoze/vhm/tests/test_middleware.py
==============================================================================
--- (empty file)
+++ repoze.vhm/trunk/repoze/vhm/tests/test_middleware.py Sun Mar 9 23:41:49 2008
@@ -0,0 +1,130 @@
+##############################################################################
+#
+# Copyright (c) 2008 Agendaless Consulting and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the BSD-like license at
+# http://www.repoze.org/LICENSE.txt. A copy of the license should accompany
+# this distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL
+# EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND
+# FITNESS FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+import unittest
+
+class TestXHeaders(unittest.TestCase):
+ def _getTargetClass(self):
+ from repoze.vhm.middleware import VHMFilter
+ return VHMFilter
+
+ def _makeOne(self, app):
+ return self._getTargetClass()(app)
+
+ def test___call___no_markers_unchanged(self):
+ # Environments which do not have markers don't get munged.
+ expected = {}
+ app = VHMTestApp(expected)
+ filter = self._makeOne(app)
+ REAL_PATH = '/a/b/c/'
+ environ = {'wsgi.url_scheme': 'http',
+ 'SERVER_NAME': 'example.com',
+ 'SERVER_PORT': '8888',
+ 'SCRIPT_NAME': '/',
+ 'PATH_INFO': REAL_PATH,
+ }
+
+ filter(environ, noopStartResponse)
+
+ self.assertEqual(expected.get('wsgi.url_scheme'), 'http')
+ self.assertEqual(expected['SERVER_NAME'], 'example.com')
+ self.assertEqual(expected['SERVER_PORT'], '8888')
+ self.assertEqual(expected['SCRIPT_NAME'], '/')
+ self.assertEqual(expected['PATH_INFO'], REAL_PATH)
+ self.assertEqual(expected.get('repoze.vhm.virtual_root'), None)
+ self.assertEqual(expected.get('repoze.vhm.virtual_host_base'), None)
+
+ def test___call___X_VHM_HOST_only_explicit_port(self):
+ expected = {}
+ app = VHMTestApp(expected)
+ filter = self._makeOne(app)
+ REAL_PATH = '/a/b/c/'
+ X_VHM_HOST = 'http://example.com:80/script'
+ environ = {'wsgi.url_scheme': 'http',
+ 'SERVER_NAME': 'localhost',
+ 'SERVER_PORT': '8080',
+ 'SCRIPT_NAME': '/',
+ 'PATH_INFO': REAL_PATH,
+ 'HTTP_X_VHM_HOST': X_VHM_HOST,
+ }
+
+ filter(environ, noopStartResponse)
+
+ self.assertEqual(expected['wsgi.url_scheme'], 'http')
+ self.assertEqual(expected['SERVER_NAME'], 'example.com')
+ self.assertEqual(expected['SERVER_PORT'], '80')
+ self.assertEqual(expected['SCRIPT_NAME'], '/script')
+ self.assertEqual(expected['PATH_INFO'], REAL_PATH)
+ self.assertEqual(expected['repoze.vhm.virtual_host_base'],
+ 'example.com:80')
+
+ def test___call___X_VHM_HOST_only_default_port(self):
+ expected = {}
+ app = VHMTestApp(expected)
+ filter = self._makeOne(app)
+ REAL_PATH = '/a/b/c/'
+ X_VHM_HOST = 'http://example.com:80/script'
+ environ = {'wsgi.url_scheme': 'http',
+ 'SERVER_NAME': 'localhost',
+ 'SERVER_PORT': '8080',
+ 'SCRIPT_NAME': '/',
+ 'PATH_INFO': REAL_PATH,
+ 'HTTP_X_VHM_HOST': X_VHM_HOST,
+ }
+
+ filter(environ, noopStartResponse)
+
+ self.assertEqual(expected['wsgi.url_scheme'], 'http')
+ self.assertEqual(expected['SERVER_NAME'], 'example.com')
+ self.assertEqual(expected['SERVER_PORT'], '80')
+ self.assertEqual(expected['SCRIPT_NAME'], '/script')
+ self.assertEqual(expected['PATH_INFO'], REAL_PATH)
+ self.assertEqual(expected.get('repoze.vhm.virtual_root'), None)
+ self.assertEqual(expected['repoze.vhm.virtual_host_base'],
+ 'example.com:80')
+
+ def test___call___X_VHM_ROOT(self):
+ expected = {}
+ app = VHMTestApp(expected)
+ filter = self._makeOne(app)
+ REAL_PATH = '/a/b/c/'
+ X_VHM_ROOT = '/a/b'
+ environ = {'wsgi.url_scheme': 'http',
+ 'SERVER_NAME': 'localhost',
+ 'SERVER_PORT': '8080',
+ 'SCRIPT_NAME': '/',
+ 'PATH_INFO': REAL_PATH,
+ 'HTTP_X_VHM_ROOT': X_VHM_ROOT,
+ }
+
+ filter(environ, noopStartResponse)
+
+ self.assertEqual(expected.get('wsgi.url_scheme'), 'http')
+ self.assertEqual(expected['SERVER_NAME'], 'localhost')
+ self.assertEqual(expected['SERVER_PORT'], '8080')
+ self.assertEqual(expected['SCRIPT_NAME'], '/')
+ self.assertEqual(expected['PATH_INFO'], REAL_PATH)
+ self.assertEqual(expected.get('repoze.vhm.virtual_root'), '/a/b')
+
+def noopStartResponse(status, headers):
+ pass
+
+class VHMTestApp:
+ def __init__(self, _called_environ):
+ self._called_environ = _called_environ
+
+ def __call__(self, environ, start_response):
+ self._called_environ.clear()
+ self._called_environ.update(environ)
+ return self.__class__.__name__
Added: repoze.vhm/trunk/repoze/vhm/tests/test_utils.py
==============================================================================
--- (empty file)
+++ repoze.vhm/trunk/repoze/vhm/tests/test_utils.py Sun Mar 9 23:41:49 2008
@@ -0,0 +1,145 @@
+##############################################################################
+#
+# Copyright (c) 2008 Agendaless Consulting and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the BSD-like license at
+# http://www.repoze.org/LICENSE.txt. A copy of the license should accompany
+# this distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL
+# EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND
+# FITNESS FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+import unittest
+
+class Test_setServerURL(unittest.TestCase):
+
+ def _getFUT(self):
+ from repoze.vhm.utils import setServerURL
+ return setServerURL
+
+ def test_empty(self):
+ setServerURL = self._getFUT()
+ environ = {}
+ setServerURL(environ)
+
+ self.assertEqual(environ,
+ {'SERVER_URL': 'http://localhost:8080'})
+
+ def test_without_url_scheme(self):
+ setServerURL = self._getFUT()
+ environ = {'wsgi.url_scheme': 'http',
+ 'SERVER_NAME': 'example.com',
+ 'SERVER_PORT': '8000',
+ 'SCRIPT_NAME': '/script',
+ }
+ setServerURL(environ)
+
+ self.assertEqual(environ['SERVER_URL'],
+ 'http://example.com:8000')
+
+ def test_with_default_port(self):
+ setServerURL = self._getFUT()
+ environ = {'wsgi.url_scheme': 'http',
+ 'SERVER_NAME': 'example.com',
+ 'SERVER_PORT': '80',
+ 'SCRIPT_NAME': '/script',
+ }
+ setServerURL(environ)
+
+ self.assertEqual(environ['SERVER_URL'],
+ 'http://example.com')
+
+ def test_with_alternate_port(self):
+ setServerURL = self._getFUT()
+ environ = {'wsgi.url_scheme': 'https',
+ 'SERVER_NAME': 'example.com',
+ 'SERVER_PORT': '4433',
+ 'SCRIPT_NAME': '/script',
+ }
+ setServerURL(environ)
+
+ self.assertEqual(environ['SERVER_URL'],
+ 'https://example.com:4433')
+
+ def test_https_without_url_scheme_with_default_port(self):
+ # In case of a PEP 333 violation.
+ setServerURL = self._getFUT()
+ environ = {'HTTPS': 'on',
+ 'SERVER_NAME': 'example.com',
+ 'SERVER_PORT': '443',
+ 'SCRIPT_NAME': '/script',
+ }
+ setServerURL(environ)
+
+ self.assertEqual(environ['SERVER_URL'],
+ 'https://example.com')
+
+ def test_with_http_host_has_port(self):
+ setServerURL = self._getFUT()
+ environ = {'SERVER_NAME': 'example.com',
+ 'SERVER_PORT': '8081',
+ 'SCRIPT_NAME': '/script',
+ 'HTTP_HOST':'localhost:8080',
+ }
+ setServerURL(environ)
+ self.assertEqual(environ['SERVER_URL'], 'http://localhost:8080')
+
+ def test_with_http_host_has_default_port(self):
+ setServerURL = self._getFUT()
+ environ = {'SERVER_NAME': 'example.com',
+ 'SERVER_PORT': '80',
+ 'SCRIPT_NAME': '/script',
+ 'HTTP_HOST':'localhost:80',
+ }
+ setServerURL(environ)
+ self.assertEqual(environ['SERVER_URL'], 'http://localhost')
+
+ def test_with_http_host_no_port(self):
+ setServerURL = self._getFUT()
+ environ = {'SERVER_NAME': 'example.com',
+ 'SERVER_PORT': '8081',
+ 'SCRIPT_NAME': '/script',
+ 'HTTP_HOST':'localhost',
+ }
+ setServerURL(environ)
+ self.assertEqual(environ['SERVER_URL'], 'http://localhost')
+
+ def test_vhm_host_base_trumps_http_host(self):
+ setServerURL = self._getFUT()
+ environ = {'SERVER_NAME': 'example.com',
+ 'SERVER_PORT': '8081',
+ 'SCRIPT_NAME': '/script',
+ 'HTTP_HOST':'localhost:8080',
+ 'repoze.vhm.virtual_host_base':'www.example.com:80',
+ }
+ setServerURL(environ)
+ self.assertEqual(environ['SERVER_URL'], 'http://www.example.com')
+
+ def test_vhm_host_base_no_port(self):
+ setServerURL = self._getFUT()
+ environ = {'SERVER_NAME': 'example.com',
+ 'SERVER_PORT': '8081',
+ 'SCRIPT_NAME': '/script',
+ 'HTTP_HOST':'localhost:8080',
+ 'repoze.vhm.virtual_host_base':'www.example.com',
+ }
+ setServerURL(environ)
+ self.assertEqual(environ['SERVER_URL'], 'http://www.example.com')
+
+class Test_getVirtualRoot(unittest.TestCase):
+ def _getFUT(self):
+ from repoze.vhm.utils import getVirtualRoot
+ return getVirtualRoot
+
+ def test_without_virtual_root(self):
+ environ = {}
+ f = self._getFUT()
+ self.assertEqual(f(environ), None)
+
+ def test_with_virtual_root(self):
+ environ = {'repoze.vhm.virtual_root':'/abc'}
+ f = self._getFUT()
+ self.assertEqual(f(environ), '/abc')
Added: repoze.vhm/trunk/repoze/vhm/utils.py
==============================================================================
--- (empty file)
+++ repoze.vhm/trunk/repoze/vhm/utils.py Sun Mar 9 23:41:49 2008
@@ -0,0 +1,57 @@
+##############################################################################
+#
+# Copyright (c) 2008 Agendaless Consulting and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the BSD-like license at
+# http://www.repoze.org/LICENSE.txt. A copy of the license should accompany
+# this distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL
+# EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND
+# FITNESS FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+from urlparse import urlunsplit
+
+from repoze.vhm.constants import DEFAULT_PORTS
+
+def setServerURL(environ):
+ """ Compute Zope2 'SERVER_URL' using WSGI environment.
+
+ o Write the key into the environment.
+ """
+ scheme = environ.get('wsgi.url_scheme')
+ if scheme is None:
+ scheme = 'HTTPS' in environ and 'https' or 'http'
+
+ http_host = environ.get('HTTP_HOST')
+
+ # if vhm specifies a virtual host base, prefer it over the http
+ # host
+ vhm_host_base = environ.get('repoze.vhm.virtual_host_base')
+
+ http_host = vhm_host_base or http_host
+
+ if http_host:
+ if ':' in http_host:
+ host, port = http_host.split(':', 1)
+ else:
+ host = http_host
+ port = None
+ else:
+ host = environ.get('SERVER_NAME', 'localhost')
+ port = environ.get('SERVER_PORT', '8080')
+
+ script_name = environ.get('SCRIPT_NAME', '/')
+
+ if port is not None and port != DEFAULT_PORTS.get(scheme):
+ netloc = '%s:%s' % (host, port)
+ else:
+ netloc = host
+
+ url = urlunsplit((scheme, netloc, '', '', ''))
+ environ['SERVER_URL'] = url
+
+def getVirtualRoot(environ):
+ return environ.get('repoze.vhm.virtual_root')
Modified: repoze.vhm/trunk/setup.py
==============================================================================
--- repoze.vhm/trunk/setup.py (original)
+++ repoze.vhm/trunk/setup.py Sun Mar 9 23:41:49 2008
@@ -1,4 +1,4 @@
-__version__ = '0.3'
+__version__ = '0.4'
import os
from setuptools import setup, find_packages
@@ -34,7 +34,6 @@
test_suite = "repoze.vhm.tests",
entry_points="""
[paste.filter_app_factory]
- vhm_zope2 = repoze.vhm.zope2:make_filter
vhm_xheaders = repoze.vhm.xheaders:make_filter
""",
)
More information about the Repoze-checkins
mailing list