VirtualHosting
VirtualHosting
Status
Author
Sidnei da Silva, Marius Gedminas
Problem/Proposal
As soon as people start putting Zope 3 in production, there will be a need for virtual hosting on Zope 3. There are several use cases of Virtual Hosting:
- Hosting various Zope servers being proxied by Apache
- Various sites inside the same Zope server, proxied by Apache
- Having a Zope server appear as a part of a site being served from Apache, with or without URL rewriting (eg: serving http://zopesite/bla as http://apachesite/dynamic/ble)
- Serving content straight out from a Zope server, without Apache.
Goals
We will try to handle the first 3 use cases with this proposal. In Zope 2, they are handled by the VirtualHostMonster? which seems to do its job very well.
The fourth one is also handled by VHM in Zope 2, but in our case it will be based on the infrastructure of the first three.
Proposed Solution
VHM's functionality could be split into two parts:
- Special URL components (VirtualHostBase?, VirtualHostRoot?,
_vh_) influencing URLs? generated inside Zope - A simple mapping from hostnames to folders that allows you to do simple virtual hosting without Apache
The first part can be implemented as a Zope 3 namespace. I propose the following syntax:
http://host:port/a/b/c/++vh++https:newhost:newport/x/y/z/++/d/e/f
would mean that an object at /a/b/c/d/e/f is published with a virtual URL of:
https://newhost:newport/x/y/z/d/e/f
Zope 2 equivalent would be:
http://host:port/a/b/c/VirtualHostBase/https/newhost:newport/VirtualHostRoot/_vh_x/_vh_y/_vh_z/d/e/f
The rules are simple:
- everything to the left of ++vh++ is traversed but stripped from the URL
- the part after ++vh++ until the next slash overrides protocol, host and port (like VirtualHostBase? in Z2 VHM), if specified.
- everything after /++vh++.../ up to /++/ is ignored for traversal but inserted at the start of the URL (this part could be empty, in which case /++/ simply does not show up in the URL)
- the rest is traversed normally
Here are some examples:
http://host:port/++vh++https:newhost:newport/d/e/f
-- just replace http://host:port to https://newhost:newport
http://host:port/++vh++/x/y/z/++/d/e/f
-- just insert /x/y/z at the start of generated URLs
http://host:port/a/b/c/++vh++/d/e/f
-- just remove /a/b/c from the start of generated URLs
http://host:port/a/b/c/++vh++/x/y/z/++/d/e/f
-- just replace /a/b/c to /x/y/z at the start of generated U
The second part, VHM-style mappings could be implemented by adding a simple
URL rewriting engine that could be processed before traversal starts. VHM
mapping rule www.foo.com/folder1 is equivalent to prepending
/folder1/++vh++/ to the start of the URL when the server name matches.
More complex cases could be handled by a more complex URL rewriting engine.
I think a separate proposal is needed.
Possible Implementation
- A ++vh++ namespace handler checks if the proto:host:port part is present, and if so, updates request._app_server via a new public method
- Clears request._traversed_names (again, a new method is needed in the interface)
- Looks for
++in request._traversal_stack, and if it finds it, moves all path elements from the top of the stack up to (but not including++) into request._app_names (again, new public method) and removes them (this time including++) from request_traversal_stack. Request already has getTraversalStack/setTraversalStack for this.
This takes care of request/URL and generated base tags
- The handler the returns the object unchanged -- this results in a
ContextWrapper? with name=
.and side_effect_name=++vh++... - Absolute URL view stops when it reaches a context wrapper with a
side_effect_name starting with
++vh++and returns request.getApplicationURL then
This takes care of @@absolute_url
- Global resources should prepend request.getApplicationURL instead of
hardcoding their location as
/@@/resourcename.
This takes care of resources.
Questions
Are there any other places where URLs? are generated?
Does virtual hosting make sense for all HTTP requests, or just browser requests?
What should be done about things acquired from outside the virtual host root? (Example: a resource defined in /aaa/++etc++services/ is used in a page rendered at /aaa/bbb/++vh++/xxx/++/ccc would think it is accessible as /aaa/@@/resource, while it should be visible as /xxx/@@/resource.)
Would it make sense to make this namespace disabled by default and make it easy to enable globally, by using a ZCML directive? (mgedmin: I think it should be enabled by default).?
Alternatives
An alternative way of implementing virtual hosting would be to create a VirtualHostingService? and require that any folder that is a root of a virtual host be converted to a site.
Most people agree that namespace-based solution is a better one.
- poster (Mar 6, 2003 1:14 pm; Comment #1)
- Use case for solution: I'd like an easy way to replace this virtual host tool with another.
Implementation suggestion: making each configuration element an object would be extremely nice, so we can have more configuration features in the future.
I'd also like to see and discuss an interface before implementation.
On one minute's thought, the namespace solution seems to me to be the better one.
- evan (Mar 6, 2003 3:29 pm; Comment #2)
- I don't have enough Zope 3 Zen to comment on service vs. namespace, but the namespace example looks plausible. Keep in mind that there are three common Virtual Hosting operations:
- Replace the host/port (VirtualHostBase?).
- Omit leading path elements after they have been traversed (VirtualHostRoot?).
- Insert leading path elements without traversing them (VirtualHostRoot?-following vh elements).
These three are independent; any combination from none to all of them may be applied in a given setup. Since this proposal is limited to considering pre-rewritten (i.e. not bare Zope) URLs?, there is no need for a SiteRoot?-like "turn off" syntax. It suffices to use an access path that hasn't been rewritten, such as direct-to-Zope or handled by a different Apache RewriteRule?.
- mgedmin (Apr 14, 2003 10:00 +0300; Comment #3)
- I've integrated my previous comment about a namespace-based implementation into the proposal itself.
