Thursday, 12 November 2015

URL Mapping and Deep Linking

A strength of Sling is the automatic and expected way that resources are structured and exposed in a logical, ordered manner. For example, AEM, by configuration allows page access through the /content/ directory. A typical page URL would be access with a browser visit to /content/projectname/pagename/subpagename.html. The minimal effort in maintaining this structure has its benefits, but changing that structure to fulfill business needs can be troublesome. Thankfully, AEM provides a number of tools and techniques to do so. This text will explore some of those options.
Root Mapping: The most common change is the need to hide the /content/ node or at least offer top-level pages at the root level. So, instead of a user typing “,” they should be able to type “” to reach the home page.
Normally, in a production environment, this is configured in front-facing web server like Apache with some configuration in the httpd.conf file using mod_rewrite. But it can also be done in AEM with some OSGi configuration:
Open Tools
Open OSGi Console
Search for and open Day CQ Root Mapping
Change the Traget (sic) Path property to whereever you'd like the redirect
Tip 1: If you like the old CQ5.5 dev landing page compared to AEM5.6, change projects.html to welcome.html
Tip 2: Other mechanisms for remapping URLs, which are discussed in this article, will break author instances because it interferes with things like authentication. Use the method above, which is safe, to remap the root node
Page Redirects: Sometimes pages are meant to simply be ways of grouping subpages, and not locations that a user should land on directly. These kind of pages can be set up as redirect component. A good example is the /content/geometrixx sample page.
To recreate this page redirect, either set it up when creating the page in AEM’s site builder(under New Page -> Advanced -> Redirect), or just change the properties of that page in CRX:
expand the content/{page} node
Click the ./jcr:content node
Change the sling:resourceType property to be foundation/components/redirect
Add a new String property called redirectTarget
Give redirectTarget a value of the new page (e.g. /content/myproject/mypage/mysubpage)
Tip 1: If a site is being built in one language, there’s no need to mimic the /en/ structure shown in the geometrixx example.
Tip 2: The sling extension (e.g. .html) will automatically carry over to the redirect page, and shouldn’t be specified
sling:Mapping Redirects: AEM’s most powerful URL-manipulation feature, a set of redirect components, is often overlooked because application servers don’t traditionally have this ability. But CQ’s built in Vanity URL support, namespace mangling, and internal tools all make use of this ability. A custom application can too, for instance, by remapping all /content project to /content/myproject
In CRX, navigate to the /etc/map node.
Open (or create) the http node of type sling:Folder
Create a node called content of type sling:Mapping
Add a property called sling:match and give it a value of localhost.4502/content/
Add a property called sling:internalRedirect and give it a value of /content/myproject
Now navigate to http://localhost:4502/content/mypage.html. The browser will display the URL that was entered, but internally AEM will be referencing the mapped directory structure.
Another way to test how CQ is handling mapping is by opening the Sling Resource Resolver tool. Log in with normal admin credentials (the default being admin/admin), enterhttp://localhost:4502/content/mypage.html into the test box, click Resolve and examine the “path” property that is output below the test box.
Problem: Remappping all of /content will also remap /content/dam, breaking current links
Solution: Override that particular mapping to point to itself
Within CRX, navigate to the /etc/map/http node.
Create a node called content_dam of type sling:Mapping
Add a property called sling:match and give it a value of localhost.4502/content/dam/
Add a property called sling:internalRedirect and give it a value of /content/dam/
This node will point to itself, and override the above /content/ mapping. The mapping rule resolution I believe is determined by string length and can be manipulated with sling:OrderedFolder. If readers have experience with this, please add comments below. It hasn’t been necessary to experiment with this feature for my projects.
The above problem will be more apparent if, instead of /content/ being mapping to the content directory, the root directory is also mapped.
Tip: Do not remap the root directory using this technique. There is a better technique above
While I recommend against remapping the root directory on author instances, as it will break things like authentication and CRX, it can still be done. In which case, the following directories also need to be remapped to point to themselves:
This should allow most applications and features of AEM to still work. But some monitoring of the app should take place to make sure other locations are not inappropriately being remapped.
Tip: If there’s a question about which URLs are being accessed by browsers or CRX, a tool like Fiddlercan monitor and report on it.
Dynamic Redirects: Thankfully, both the sling:match and sling:internalRedirect nodes use regular expressions, so that URL mapping can be more dynamic. So things like top-level links can be remapped to strip off the “.html” extension.
Within /etc/map/http
Create a new node named posts of type sling:Mapping
Add a property called sling:match with value localhost.4502/posts/([^/]+)$
Add a property called sling:internalRedirect with value /content/myproject/posts/$1.html
This will allow posts to be accessed without an extension. There are other ways of performing this particular task, such as adding a GET.jsp entry to the components, but mapping redirects are the best way to not interfere with the rest of the Sling resolution logic.
Deep Linking: When taking advantage of dynamic sling:Mappings with regular expressions, URL deep-linking can be implemented without the use of URL parameters or javascript. In some cases, SEO (Search Engine Optimization) experts will advise that sub-pages be reached from URLs and get loaded on the initial request. Other needs like analytics engines might preclude the use of hash tags or URL parameters. In this case, AEM can leverage URL mappings and selectors to pass information to a component and preload content.
In the posts node above, for instance, we can instead change the mapping from going to post sub pages to the posts page directly. Here, assume there is some component inside the post page that loads properties from its child page. But it needs to know which child page is being accessed.
Add a property called sling:match with value localhost.4502/posts/([^/]+)$
Add a property called sling:internalRedirect with value /content/myproject/posts.$1.html
The mapping above will take a request to /posts/child-page-name, and remap it to /posts.child-page-name.html. Essentially, this is the same as a posts.html call, with the addition of a component now being able to use the sling Resource API to extract that selector. The code within such a component would look something like this:
String defaultPostName = "";
//Below is logic to default posts based on page selectors.
//e.g. posts.{post-name.}.html
String selectorPath = currentPage.adaptTo(Resource.class).getResourceMetadata().getResolutionPathInfo();
String selectors[] = selectorPath.split("\\.");
if (selectors.length > 2) {
defaultPostName = selectors[1];
view rawposts.jsp
Tip 1: The dollar sign ($) above tells the regex “this is the end of the string. AEM therefore won’t map any URL with additional characters in the URL. However, URL parameters and hash tags will be ignored for the purposes of mapping, and don’t need to be considered
Tip 2: The technique demonstrated above will extract selectors from a page. Multiple can be stacked with additions /([^/]+) references in the sling:match property, and $2, $3… variable references in the sling:match property
Tip 3: Selectors can also be added to components using sling:include tags. To get a parent resource containing that information, use componentContent.getResource() in place of the currentPage.adaptTo(Resource.class) reference above
Summary: CQ offers a number of techniques to remap pages and URLs. While most of this can and should be done on a proxy web server, some powerful mapping tools are available directly in CQ. The topic is only superficially covered here, and any shared experiences or tips from readers are welcome in the comments below.

1 comment :

  1. Hi, can you help on this, for an example I need to change:

    Best Regards