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 VirtualURIManager via 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 VirtualUriManagerAdapter class, internally delegating to the registry
  • VirtualURIManager is 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:

  • Registry is 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 the MappingResult of 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-118PageNameColumnFormatter now 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#getRequest is documented as “Avoid calls to this method wherever possible.”
  • In theory, fetching serverName from HttpServletRequest could 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 VirtualUriMapping API
  • to pass a more complete URI (if not full URL) to its single #mapURI method—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 separate Comparator.
  • eventually to split mapURI vs. matchesURI?

References:

  1. HttpServletRequest#getRequestURI merely strips domain and query-string
  2. our ContentTypeFilter / ServletUtils further 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 @FunctionalInterface too

6. Deprecations

  • Content2Bean adders and empty getter for HostBased-mappings
  • VirtualURIManager#getInstance goes away pretty much for free

Known consumers

ModuleUsage
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/
-editVirtualUris/availability/rules/VirtualUriMappingEditingEnabledRule

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 appVirtual URI Mappings subapp
Pages

Displays conflicting virtual URIs

PAGES-118 - Getting issue details... STATUS


Blossom

BLOSSOM-4 - Getting issue details... STATUS

Blossom module
Vanity URLsVanity Url App




  • No labels

1 Comment

  1. Outcome from architects:

    • start with compatibility adapters for manager + mapping
      • + part of functional evaluation
    • observe both old and new JCR locations for virtualUriMappings
    • general agreement about other points
      • tentatively starting with proposed new mapping API (w/ Optional<URI>)
    • will complete the page with other improvement ideas (multisite, author/public)