Virtual URI mappings are currently being relocated to their own core module: magnolia-virtual-uri. See MAGNOLIA-3349.
As most classes are being duplicated for backwards compatibility, there is potential to improve some caveats with current implementation, removing some deprecations, as well as reconsidering the role of some components.
MAGNOLIA-3349 - Getting issue details... STATUS
1. From VirtualURIManager to VirtualUriRegistry - compatibility
Given:
- A. Many components or depending modules use the Virtual URI functionality. They typically inject the
VirtualURIManagervia IoC. - B. The new virtual-uri module is a descendent module of core & config in the main reactor; it will be included in our webapps, but may not be present in theirs (customers').
We acknowledge:
- Creation of a
VirtualUriManagerAdapterclass, internally delegating to the registry VirtualURIManageris de-finalized- Rebinding the manager to the adapter via module descriptor—virtual-uri module will be loaded after core anyways
2. Evaluation of URI mappings
Given:
Registryis a config API; it is not intended to host the evaluation of URI mappings, like the manager did- Evaluation is currently done as
VirtualURIManager#getURIMapping
We propose:
- to simply move that out to the
VirtualUriFilter, as a private/protected method named#resolve/find/applyUriMapping - leaning towards
“apply”because it does not only resolve the best-matching URI mapping, but also returns theMappingResultof applying it to the given URI/query string.
Usage search on Bitbucket revealed very few occurrences of invoking evaluation straight.
- a customer project has a custom logout filter dispatching the request to whatever URI is mapped to "/" (aka default URI mapping)
- is that needed at all?
- or should that be done in the product? (e.g. for public)
- since PAGES-118,
PageNameColumnFormatternow displays conflicting virtual URIs- that one could query the registry instead; it does not need the mapping result
- corporate website extends the
VirtualUriFilter
3. Host-based & Query-aware mappings
Problem:
The VirtualURIMapping interface takes a URI (string), which is stripped from its domain, query-string (by servlet spec[1]) and from its context path (by us[2]).
Over time, there was need for URI mappings based on host-name (since MAGNOLIA-2846), as well as query parameters (since MAGNOLIA-3842).
MappingResult mapURI(String uri);
The HostBasedVirtualURIMapping and its regex sibling were introduced; they resolve the host via MgnlContext.
String requestHost = ((WebContext) MgnlContext.getInstance()).getRequest().getServerName();WebContext#getRequestis documented as “Avoid calls to this method wherever possible.”- In theory, fetching
serverNamefromHttpServletRequestcould differ from what's in the aggregation-state, couldn't it?
The QueryAwareVirtualURIMapping sub-interface was introduced; it instructed the VirtualURIManager to bypass the original mapping API in favor of the more specific one.
MappingResult mapURI(String uri, String queryString);
We have two approaches to a similar problem; mind that both approaches cannot really be built upon. The former suggest subclassing to get the host resolution; the latter is tightly coupled to the manager.
More generally, and conceptually, Virtual URI mappings receive an incoming URI from the filter, and if they match, respond with a rerouted URI.
Therefore we propose:
- to amend the newly-relocated
VirtualUriMappingAPI - to pass a more complete URI (if not full URL) to its single
#mapURImethod—from which both host-name and query-parameters could be retrieved, e.g.Optional<URI> mapURI(URI browserUri);
- to replace length matching with implementation of
Comparable<VirtualUriMapping>, or separateComparator. - eventually to split mapURI vs. matchesURI?
References:
HttpServletRequest#getRequestURImerely strips domain and query-string- our
ContentTypeFilter/ServletUtilsfurther strip the context path
4. VirtualUriMapping - compatibility from info.magnolia.cms.beans.config.VirtualURIMapping
Similarly to the VirtualUriManagerAdapter, the old VirtualURIMapping interface itself needs an adapter towards the relocated API.
This is essentially a wrapper class built from the old mapping, delegating mapping to it, and returning a similarly wrapped MappingResult (or however the API evolves there).
- This allows us *not* to be forced to migrate previous URI mappings from the very start.
- effectively buying us some time to reintroduce host-based and query-aware mappings.
- This also guarantees customers' custom mappings will continue to work within the new registry.
5. Functionalism
- Evaluation of URI mappings in the filter or manager, as well as in the host-based variation could use Java 8 functional APIs, mostly streams for clarity.
- finding mapping with greatest length, seems like a good fit; blends well with proposal above for Comparables
- VirtualUriMapping could become
@FunctionalInterfacetoo
6. Deprecations
- Content2Bean adders and empty getter for HostBased-mappings
VirtualURIManager#getInstancegoes away pretty much for free
Known consumers
| Module | Usage | |
|---|---|---|
| Activation | /modules/activation/virtualURIMapping/3_0_to_3_5 | from /ActivationHandler to forward:/.magnolia/activation |
| Admincentral | /modules/ui-admincentral/virtualURIMapping/default@toURI | from / to redirect:/.magnolia/admincentral (author) or redirect:/travel.html (public) |
| Google Sitemaps | /modules/google-sitemap/virtualURIMapping/siteMaps /modules/google-sitemap/apps/siteMaps/subApps/browser/actions/ | to redirect:/sitemaps |
| RSS Aggregator | /modules/rssaggregator/virtualURIMapping/rssFeeds /modules/rssaggregator/virtualURIMapping/planetFeeds /modules/rssaggregator/virtualURIMapping/categoryFeeds | from /rssFeeds/* to redirect:/rss/?... from /planetFeeds/* to redirect:/rss/?generatorName=planet&... from /categoryFeeds/* to redirect:/rss/?generatorName=category&... |
| Tours | /modules/tours/virtualURIMapping/travelToursMapping /modules/tours/virtualURIMapping/sportstationToursMapping | from /tours(.*).html to forward:/tour?tour=$1 from /tours(.*).html to forward:/tour?tour=$1 |
| About app | Virtual URI Mappings subapp | |
| Pages | Displays conflicting virtual URIs PAGES-118 - Getting issue details... STATUS | |
| Blossom | BLOSSOM-4 - Getting issue details... STATUS | Blossom module |
| Vanity URLs | Vanity Url App |
1 Comment
Mikaël Geljić
Outcome from architects: