From d9d3f33ee37aa728da35003bfe7bb1ab5b83f791 Mon Sep 17 00:00:00 2001 From: David Glick Date: Wed, 1 Apr 2026 10:27:32 -0700 Subject: [PATCH] Fix traversal of virtual-hosted subsites --- news/99.bugfix | 1 + src/plone/rest/tests/test_traversal.py | 14 +++++++++++++- src/plone/rest/traverse.py | 5 ++++- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 news/99.bugfix diff --git a/news/99.bugfix b/news/99.bugfix new file mode 100644 index 00000000..938aeeab --- /dev/null +++ b/news/99.bugfix @@ -0,0 +1 @@ +Fix traversal with virtual hosting with a subsite as the VirtualHostRoot. @davisagli diff --git a/src/plone/rest/tests/test_traversal.py b/src/plone/rest/tests/test_traversal.py index a7be6714..98210bd7 100644 --- a/src/plone/rest/tests/test_traversal.py +++ b/src/plone/rest/tests/test_traversal.py @@ -141,7 +141,19 @@ def test_virtual_hosting(self): vhm.addToContainer(app) obj = self.traverse( path="/VirtualHostBase/http/localhost:8080/plone/VirtualHostRoot/" - ) # noqa + ) + self.assertTrue(isinstance(obj, Service), "Not a service") + del app["virtual_hosting"] + + def test_virtual_hosting_subpath(self): + app = self.layer["app"] + vhm = VirtualHostMonster() + vhm.id = "virtual_hosting" + vhm.addToContainer(app) + self.portal.invokeFactory("Document", id="doc1") + obj = self.traverse( + path="/VirtualHostBase/http/localhost:8080/plone/doc1/VirtualHostRoot" + ) self.assertTrue(isinstance(obj, Service), "Not a service") del app["virtual_hosting"] diff --git a/src/plone/rest/traverse.py b/src/plone/rest/traverse.py index bd210312..ed96145c 100644 --- a/src/plone/rest/traverse.py +++ b/src/plone/rest/traverse.py @@ -112,7 +112,10 @@ def publishTraverse(self, request, name): try: obj = adapter.publishTraverse(request, name) if not IContentish.providedBy(obj) and not IService.providedBy(obj): - raise KeyError + if isinstance(obj, VirtualHostMonster): + return obj + else: + raise KeyError # If there's no object with the given name, we get a KeyError. # In a non-folderish context a key lookup results in an AttributeError.