Commit a76325fd authored by Evan Simpson's avatar Evan Simpson

Collector #809: Added and documented Traversable.py methods absolute_url_path...

Collector #809: Added and documented Traversable.py methods absolute_url_path and virtual_url_path, and reverted earlier change to absolute_url behaviour.
parent 27188f79
......@@ -12,8 +12,8 @@
##############################################################################
__doc__='''Application support
$Id: Application.py,v 1.196 2003/11/28 16:45:25 jim Exp $'''
__version__='$Revision: 1.196 $'[11:-2]
$Id: Application.py,v 1.197 2003/12/10 17:52:46 evan Exp $'''
__version__='$Revision: 1.197 $'[11:-2]
import Globals,Folder,os,sys,App.Product, App.ProductRegistry, misc_
import time, traceback, os, Products
......@@ -137,21 +137,24 @@ class Application(Globals.ApplicationDefaultPermissions,
test_url=ZopeAttributionButton
def absolute_url(self, relative=0):
'''Return a canonical URL for this object based on its
physical containment path, possibly modified by virtual hosting.
If the optional 'relative' argument is true, only return the
path portion of the URL.'''
'''The absolute URL of the root object is BASE1 or "/".'''
if relative: return ''
try:
# We need a REQUEST that uses physicalPathToURL to create
# BASE1 and BASEPATH1, so probe for it.
req = self.REQUEST
req.physicalPathToURL
except AttributeError:
return ''
# Take advantage of computed URL cache
if relative:
return req['BASEPATH1'][1:]
return req['BASE1']
# Take advantage of computed URL cache
return self.REQUEST['BASE1']
except (AttributeError, KeyError):
return '/'
def absolute_url_path(self):
'''The absolute URL path of the root object is BASEPATH1 or "/".'''
try:
return self.REQUEST['BASEPATH1']
except (AttributeError, KeyError):
return '/'
def virtual_url_path(self):
'''The virtual URL path of the root object is empty.'''
return ''
def getPhysicalPath(self):
'''Returns a path that can be used to access this object again
......
......@@ -12,8 +12,8 @@
##############################################################################
'''This module implements a mix-in for traversable objects.
$Id: Traversable.py,v 1.22 2003/11/28 16:45:44 jim Exp $'''
__version__='$Revision: 1.22 $'[11:-2]
$Id: Traversable.py,v 1.23 2003/12/10 17:52:46 evan Exp $'''
__version__='$Revision: 1.23 $'[11:-2]
from Acquisition import Acquired, aq_inner, aq_parent, aq_base
......@@ -31,20 +31,63 @@ class Traversable:
absolute_url__roles__=None # Public
def absolute_url(self, relative=0):
'''Return a canonical URL for this object based on its
physical containment path, possibly modified by virtual hosting.
If the optional 'relative' argument is true, only return the
path portion of the URL.'''
"""
Return the absolute URL of the object.
This a canonical URL based on the object's physical
containment path. It is affected by the virtual host
configuration, if any, and can be used by external
agents, such as a browser, to address the object.
If the relative argument is provided, with a true value, then
the value of virtual_url_path() is returned.
Some Products incorrectly use '/'+absolute_url(1) as an
absolute-path reference. This breaks in certain virtual
hosting situations, and should be changed to use
absolute_url_path() instead.
"""
if relative:
return self.virtual_url_path()
spp = self.getPhysicalPath()
try:
toUrl = self.REQUEST.physicalPathToURL
except AttributeError:
return '/'.join(map(quote, spp[1:]))
if relative:
# Remove leading slash for backward compatibility sake.
return toUrl(spp, relative)[1:]
return path2url(spp[1:])
return toUrl(spp)
absolute_url_path__roles__=None # Public
def absolute_url_path(self):
"""
Return the path portion of the absolute URL of the object.
This includes the leading slash, and can be used as an
'absolute-path reference' as defined in RFC 2396.
"""
spp = self.getPhysicalPath()
try:
toUrl = self.REQUEST.physicalPathToURL
except AttributeError:
return path2url(spp) or '/'
return toUrl(spp, relative=1) or '/'
virtual_url_path__roles__=None # Public
def virtual_url_path(self):
"""
Return a URL for the object, relative to the site root.
If a virtual host is configured, the URL is a path relative to
the virtual host's root object. Otherwise, it is the physical
path. In either case, the URL does not begin with a slash.
"""
spp = self.getPhysicalPath()
try:
toVirt = self.REQUEST.physicalPathToVirtualPath
except AttributeError:
return path2url(spp[1:])
return path2url(toVirt(spp))
getPhysicalRoot__roles__=() # Private
getPhysicalRoot=Acquired
......@@ -159,4 +202,7 @@ class Traversable:
restrictedTraverse__roles__=None # Public
def restrictedTraverse(self, path, default=_marker):
def path2url(path):
return '/'.join(map(quote, path))
return self.unrestrictedTraverse(path, default, restricted=1)
......@@ -94,12 +94,43 @@ class ObjectManagerItem:
def absolute_url(relative=None):
"""
Return the absolute url to the object.
Return the absolute URL of the object.
If the relative argument is provided with a true value, then
the URL returned is relative to the site object. Note, if
virtual hosts are being used, then the path returned is a
logical, rather than a physical path.
This a canonical URL based on the object's physical
containment path. It is affected by the virtual host
configuration, if any, and can be used by external
agents, such as a browser, to address the object.
If the relative argument is provided, with a true value, then
the value of virtual_url_path() is returned.
Some Products incorrectly use '/'+absolute_url(1) as an
absolute-path reference. This breaks in certain virtual
hosting situations, and should be changed to use
absolute_url_path() instead.
Permission -- Always available
"""
def absolute_url_path():
"""
Return the path portion of the absolute URL of the object.
This includes the leading slash, and can be used as an
'absolute-path reference' as defined in RFC 2396.
Permission -- Always available
"""
def virtual_url_path():
"""
Return a URL for the object, relative to the site root.
If a virtual host is configured, the URL is a path relative to
the virtual host's root object. Otherwise, it is the physical
path. In either case, the URL does not begin with a slash.
Permission -- Always available
"""
......
"""Virtual Host Monster regression tests.
These tests mainly verify that OFS.Traversable.absolute_url()
works correctly in a VHM environment.
Also see http://zope.org/Collectors/Zope/809
Note: Tests require Zope >= 2.7
$Id: testVirtualHostMonster.py,v 1.2 2003/12/10 17:52:47 evan Exp $
"""
from Testing.makerequest import makerequest
import Zope
Zope.startup()
import unittest
class VHMRegressions(unittest.TestCase):
def setUp(self):
get_transaction().begin()
self.app = makerequest(Zope.app())
try:
self.app.manage_addProduct['SiteAccess'].manage_addVirtualHostMonster('VHM')
self.app.manage_addFolder('folder')
self.app.folder.manage_addDTMLMethod('doc', '')
self.app.REQUEST.set('PARENTS', [self.app])
self.traverse = self.app.REQUEST.traverse
except:
self.tearDown()
def tearDown(self):
get_transaction().abort()
self.app._p_jar.close()
def testAbsoluteUrl(self):
m = self.app.folder.doc.absolute_url
self.assertEqual(m(), 'http://foo/folder/doc')
def testAbsoluteUrlPath(self):
m = self.app.folder.doc.absolute_url_path
self.assertEqual(m(), '/folder/doc')
def testVirtualUrlPath(self):
m = self.app.folder.doc.absolute_url
self.assertEqual(m(relative=1), 'folder/doc')
m = self.app.folder.doc.virtual_url_path
self.assertEqual(m(), 'folder/doc')
def testPhysicalPath(self):
m = self.app.folder.doc.getPhysicalPath
self.assertEqual(m(), ('', 'folder', 'doc'))
def gen_cases():
for vbase, ubase in (
('', 'http://foo'),
('/VirtualHostBase/http/example.com:80', 'http://example.com'),
):
yield vbase, '', '', 'folder/doc', ubase
for vr, _vh, p in (
('folder', '', 'doc'),
('folder', 'foo', 'doc'),
('', 'foo', 'folder/doc'),
):
vparts = [vbase, vr, 'VirtualHostRoot']
if not vr:
del vparts[1]
if _vh:
vparts.append('_vh_' + _vh)
yield '/'.join(vparts), vr, _vh, p, ubase
for i, (vaddr, vr, _vh, p, ubase) in enumerate(gen_cases()):
def test(self):
ob = self.traverse('%s/%s/' % (vaddr, p))
vhp = '/' + '/'.join([x for x in _vh, p if x])
self.assertEqual(ob.absolute_url(), ubase + vhp)
self.assertEqual(ob.absolute_url_path(), vhp)
self.assertEqual(ob.absolute_url(relative=1), p)
self.assertEqual(ob.virtual_url_path(), p)
self.assertEqual(ob.getPhysicalPath(), ('', 'folder', 'doc'))
app = ob.aq_parent.aq_parent
self.assertEqual(app.absolute_url(), ubase + '/' + _vh)
self.assertEqual(app.absolute_url_path(), '/' + _vh)
self.assertEqual(app.absolute_url(relative=1), '')
self.assertEqual(app.virtual_url_path(), '')
setattr(VHMRegressions, 'testTraverse%s' % i, test)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(VHMRegressions))
return suite
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
......@@ -11,7 +11,7 @@
#
##############################################################################
__version__='$Revision: 1.93 $'[11:-2]
__version__='$Revision: 1.94 $'[11:-2]
import re, sys, os, urllib, time, random, cgi, codecs
from types import StringType, UnicodeType
......@@ -1149,7 +1149,7 @@ class HTTPRequest(BaseRequest):
v.insert(0, '')
else:
v.insert(0, other['SERVER_URL'])
URL = '/'.join(v)
URL = '/'.join(v) or '/'
if other.has_key('PUBLISHED'):
# Don't cache URLs until publishing traversal is done.
other[key] = URL
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment