Providing the ability to provide multiple virtual W*S services by extending the existing namespace/workspace filtering concept.
Under Discussion, In Progress, Completed, Rejected, Deferred
The ability to have "virtual services" is something that GeoServer users have longed for for quite some time. Currently a GeoServer instance consists of a single WFS, a single WMS, and a single WCS. This is not ideal for a number of reasons. The most prominent being that each of the three services produces every single layer in its capabilities document.
Currently users are forced to run separate GeoServer instances in order to have two separate W*S services. Apart from being an administration hassle often it is often impossible since runnign multiple GeoServer instances in a single container can often lead to problems.
A virtual service is a way to provide the appearance of multiple instances of a particular W*S service within a single installation.
The idea is to expand on the workspace filtering functionality that was implemented as described here. The current functionality allows you to append a parameter to a capabilities request like:
When specified the workspace filter will limit the capabilities document to only those layers which are contained by the specified workspace. This has the benefit of (a) allowing one to limit the size of a capabilities document and (b) provide the limited appearance of multiple W*S services.
The first step of this proposal will be to provide the ability specify the workspace filter directly in the URL path:
The result of which will have the following consequences:
- Implicitly provide the workspace filter limiting the capabilities document to layers in the specified workspace
- Force links to resources (operations) in the capabilities document to include the workspace
- Secure the service to only those layers in the specified workspace
As an example consider the following WFS capabilities request:
This would return the following (simplified) capabilities document:
Important things to note about the above capabilities document:
- The operation references contain the "topp" workspace filter
- Only those feature types in the "topp" namespace are present
Now consider the following GetFeature request:
The result of the above request would be the regular output of a GetFeature against topp:states. The only interesting aspect is that because the topp workspace is implicitly specified there is no need to qualify the typename with "topp", and it can simply be specified as typename=states.
However now consider the following request:
The above request specifies the topp workspace filter but requests a feature type that is a different namespace (sf:streams). The result of the above request would be an exception stating that "sf:streams" does not exist.
To sum up this proposal proposes the ability to specify the workspace filter directly in the URL path to the service. And in addition to filtering down the layers returned in a capabilities document it will:
- Modify operation URL's generated by the capabilities document to include the workspace component
- Automatically qualify any resources (layers, feature types, coverages) with the workspace / namespace specified in the URL
Additionally the presence of the workspace directly in the URL will lock down the current operation to only those layers in the specified workspace.
Implementing this functionality will require changes to a number of sub systems.
The ows dispatcher as written will only handle url paths that contain the service identifier. It will be need to be modified to allow for other information (in this case workspace). However since the ows dispatcher is an autonomous sub system it has no notion of what a workspace is. So the idea is to add the notion of "context" to an ows request. Which would basically make the structure of an ows url look like:
The context is essentially any additional path components that appear before the service. This context will be stored as an attribute on the org.geoserver.ows.Request class which is the class that stores all the state of a request being processed by the dispatcher.
With the workspace context available as part of a dispatcher request a simple callback can be implemented which takes the context and sets the workspace filter parameter on the current request object.
Currently when the capabilities operations see workspace filter on a request they simply filter down the layers which are produced in the capabilities document. This behavior will be extended to
ensure that any operation urls created also contain the workspace context in the path.
Currently the only way to restrict access in GeoServer to a specific set of layers is to configure the security subsystem as an administrator. However in this case this needs to be achieved dynamically. So the approach will be to implement a customized data access manager which is a wrapper around the current one. The wrapper will do a check against the current workspace filter (stored as a thread local variable) and the resource being accessed and deny access when the resource is not in the specified workspace. In all other cases it will simply delegate to the current default access manager.
One potential backwards compatibility issue could be with how to interpret the workspace parameter in a request. Currently a client can do this:
And happily get back the sf:streams features. However with this system they would be greeted with an exception.
If necessary we could track wether the workspace filter originates as a query string parameter (and allow the call) or if it comes from path context (and disallow the call).
One thing to consider is how this will interact with the resource publishing split of GeoServer 2.1.x. There is some potential overlap as the resource pub split realizes virtual services via the notion of a map. The idea to handle this is to have an automatic migration occur similar to how the upgrade from 1.7.x to 2.0 is handled. Basically when 2.1 hits a 2.0 configuration a map will be automatically created for each workspace. So the upgrade path will be clean and there should be no conflict.