Delivery Tier URLs

Introduction

Hippo's delivery tier (HST) provides URL creation out-of-the-box. It takes care of including or excluding the context path, hence, should be used for every URL, also for static resources like CSS. This way the HST application can be deployed as for example site.war, but does not show the /site context path in the URL. Combined with Apache HTTP Server configured as reverse proxy the HST can serve any scheme ( http/https), domain and port and can be deployed with any context path:

The HST creates out-of-the-box URLs for a page, a repository binary resource or a container resource (like CSS or image). The HST supports link rewriting to URLs for internal links between Hippo Documents stored in Hippo Repository. The HST does this automatically, based on the configuration of the SiteMap: It is the Request Matching reversed. For link rewriting the HST supports by default:

  1. Cross Domain / Multi Site URLs : URLs between subsites, even with different domains
  2. Cross Scheme : URLs from http to https and vice versa. Even cross domain and cross scheme links combined are supported.
  3. Channel Aware URLs : mobile URLs stay within the mobile channels, while the URLs same content for the normal website stays within the website
  4. Context Aware URLs : URLs for one and the same document can be different according the context of the current URL
  5. Canonical URLs : A URL that is independent of the context of the current URL (highly appreciated by search engines like Google, Yahoo, see canonical links)
  6. Preferred URLs : URLs for a specific part of the SiteMap only
  7. NavigationStateful URLs : URLs taking the current navigation state into account, for example to get a URL in the context of the current faceted navigation location.

In a HstComponent that extends from the org.hippoecm.hst.component.support.bean.BaseHstComponent, you can access the HstLinkCreator as follows:

public abstract class AbstractSearchComponent extends BaseHstComponent {
    @Override
    public void doBeforeRender(HstRequest request, HstResponse response)
                                             throws HstComponentException {
       // getting hold of the HippoBean for the current request (the
       // resolved sitemap item's its relative content path)
       HippoBean myBean = request.getRequestContext().getContentBean();
       // getting hold of the link creator
       HstLinkCreator linkCreator = request.getRequestContext()
                                                  .getHstLinkCreator();
       // create HstLink
       HstLink link = linkCreator.create(myBean,
                                          request.getRequestContext());
       // create the url String
       String Url = link.toUrlForm(request.getRequestContext(), false);
    }

Most of the time however, you won't need to create a URL in a HstComponent Java class, but rather create one in during the rendering of the template (jsp/freemarker). Therefore, the HST provides a custom tag, the <hst:link> tag. See at the end of this page for all the possible attributes. The <hst:link> tag is a tag that can create URLs for HippoBeans, for JCR nodes, for repository binaries, repository webfiles and for static resources. It automatically includes the context path in the URL when this is needed.

The <hst:link> tag takes an optional attribute var in which the String output if stored. If the attribute is missing, the value is directly written to the rendered output of the template.

Examples of the <hst:link> Tag

Note that out-of-the-box, the examples below for HippoBean are cross-domain, multi-site, context and channel aware!

Create a URL for a HippoBean

Assume you stored some  HippoBean objects in the documents variable below, then the JSP for creating URLs for these documents is:

<ul>
  <c:forEach var="document" items="${requestScope.documents}">
    <li>
        <hst:link var="link" hippobean="${document}"/>
        <a href="${link}">${document.title}</a>
    </li>
  </c:forEach>
</ul>

The same as above in a Freemarker template is as follows:

<ul>
  <#list documents as document>
    <li>
        <@hst.link var="link" hippobean=document/>
        <a href="${link}">${document.title}</a>
    </li>
  </#list>
</ul>
  1. If you want a canonical URL, add canonical=true to the link tag.
  2. If you want a navigationalStateful URL, add navigationalStateful=true to the link tag.
  3. If you want a preferred URL, add a <hst:sitemapitem> child to the <hst:link> tag

Create a URL for a Container Resource (For Example a CSS)

Creating a link to a CSS file:

JSP

<hst:link var="css" path="/css/style.css"/>
<link href="${css}" type="text/css"/>

Freemarker

<@hst.link var="css" path="/css/style.css"/>
<link href="${css}" type="text/css"/>

Create a URL for a Repository Resource when you know the Exact Location

Normally, you access a repository binary resource just like any other JCR node through a HippoBean wrapper. The HST linkrewriting makes sure for the beans correct binary URLs are created. If you want to create a binary URL by pointing to a repository location, this can be done by using the attr path and prefix the absolute repository location by /binaries. Suppose the binary is at /content/assets/mypdfs/test.pdf. Then this will create a repository binary link:

JSP

<hst:link var="link" path="/binaries/content/assets/mypdfs/test.pdf"/>
<a href="${link}">my pdf</a>

Freemarker

<@hst.link var="link" path="/binaries/content/assets/mypdfs/test.pdf"/>
<a href="${link}">my pdf</a>

Create a URL for a siteMapItemRefId

When you have multiple sites in multiple languages, you want to use the same JSP to say, create a hard-coded link to the contact page. However, the URL for the contact page is different for every language because every language has its own HST sitemap. For this purpose, a siteMapItemRefId can be used. Every sitemap should then have the contact sitemap item set to the same hst:refId. So, suppose every sitemap item for the contact page in every language has hst:refId = 'contactId'. Then the following code snippet creates the correct URL for each language:

JSP

<hst:link var="link" siteMapItemRefId="contactId"/>
<a href="${link}"><fmt:message key="key.contact"/></a>

Freemarker

<@hst.link var="link" siteMapItemRefId="contactId"/>
<a href="${link}"><fmt:message key="key.contact"/></a>

Create a URL for a Specific Site

By default, the HST will always try to create a URL within the current site. If instead you want to explicitly specify the site to create the URL for, you can use the mount parameter in the hst:link tag.

First, make sure the mount for the site you want to link to has an alias defined. For example:

/hst:hst/hst:hosts/dev-localhost/localhost
  + hst:root [hst:mount]
    - hst:alias = "english-website"

Then taking the previous example and changing it to always, within every site, link to the contact page on the English website, the code snippet becomes:

JSP

<hst:link var="link" mount="english-website" siteMapItemRefId="contactId"/>
<a href="${link}"><fmt:message key="key.contact"/></a>

Freemarker

<@hst.link var="link" mount="english-website" siteMapItemRefId="contactId"/>
<a href="${link}"><fmt:message key="key.contact"/></a>

Create a URL for the Current Page or Current Matched Sitemap Item

Frequently, you just need to create a URL for the current page you are at, only without request parameters. For example, if you are on a search result URL http://localhost:8080/site/search?query=foo_ and you want to go clear the search, thus go back to http://localhost:8080/site/search. You can achieve this by using the hst:link tag without path, subPath, hippobean, or siteMapItemRefId attribute. The simplest way is:

JSP

<hst:link var="link"/>
<a href="${link}">Link for currently matched sitemap item</a>

Freemarker

<@hst.link var="link"/>
<a href="${link}">Link for currently matched sitemap item</a>

Create a fullyQualified URL

When your URL needs to include the scheme, host and possibly portnumber, you can use the fullyQualified attribute.

JSP

<hst:link var="link" hippobean="${requestScope.myBean}" fullyQualified="true"/>
<a href="${link}">fully qualified link</a>

Freemarker

<@hst.link var="link" hippobean=myBean fullyQualified=true />
<a href="${link}">fully qualified link</a>

Create a Canonical URL

Search engines do not like to index the almost same html page at different URLs. Most engines (for example Yahoo, Google, Bing) support for this the concept of canonical links, see for example http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html. So, suppose in our example of /eu/climate/news/2009/mynewsitem and /news/2009/mynewsitem, then, the html of /eu/climate/news/2009/mynewsitem could contain:

<link rel="canonical" href="/news/2009/mynewsitem"/>

It means, that you indicate that search engines can find the canonical page, the page they should index, for this page at /news/2009/mynewsitem.

So, how do we achieve this in the HST2? If you use:

JSP

<hst:link hippobean="${requestScope.document}"/>

Freemarker

<@hst.link hippobean=document />

you by default get the Context Aware link. If you want the canonical version, just tell the hst:link to do so as follows:

JSP

<hst:link hippobean="${requestScope.document}" canonical="true"/>

Freemarker

<@hst.link hippobean=document canonical=true />

<tag>
  <description>This tag creates links. It knows whether to include or exclude the contextpath and servletpath. The
    attributes 'link' and 'node' get the current servletpath in their result, the 'path' attribute does *not* get the
    servletpath. The reasoning is that the 'path' attribute is used for static links, like for css and images. You
    should use one of the three attributes (link|path|node) within one tag, and not more then one. If you do not
    specify the 'var' attribute, the output is directly written. Otherwise, the value is stored in the var attribute.
    If you only specify a hst:link (with or without var), you get a hst link for the current URL
  </description>
  <name>link</name>
  <tag-class>org.hippoecm.hst.tag.HstLinkTag</tag-class>
  <tei-class>org.hippoecm.hst.tag.HstLinkTag$TEI</tei-class>
  <body-content>JSP</body-content>
  <attribute>
    <description>The variable name of the link tag</description>
    <name>var</name>
    <required>false</required>
    <rtexprvalue>false</rtexprvalue>
    <type>java.lang.String</type>
  </attribute>
  <attribute>
    <description>A HstLink object, containing a already rewritten object</description>
    <name>link</name>
    <required>false</required>
    <rtexprvalue>true</rtexprvalue>
    <type>org.hippoecm.hst.core.linking.HstLink</type>
  </attribute>
  <attribute>
    <description>A string path, typically a location relative to the webapp</description>
    <name>path</name>
    <required>false</required>
    <rtexprvalue>true</rtexprvalue>
    <type>java.lang.String</type>
  </attribute>
  <attribute>
    <description>A string subPath which gets appended to the path with a delimiter './' . This makes it useful for
      creating REST links
    </description>
    <name>subPath</name>
    <required>false</required>
    <rtexprvalue>true</rtexprvalue>
    <type>java.lang.String</type>
  </attribute>
  <attribute>
    <description>An IdentifiableContentBean object. This is typically one of your bean mapped objects</description>
    <name>hippobean</name>
    <required>false</required>
    <rtexprvalue>true</rtexprvalue>
    <type>org.hippoecm.hst.content.beans.standard.IdentifiableContentBean</type>
  </attribute>
  <attribute>
    <description>A string id, which is the refId of a sitemap item you want to link to. Note that the sitemapitem
      belonging to the refId should not be a wildcard matcher, and non of its ancestors should be a wildcard. Using
      this to create a link to a sitemap item can be handy when you know to which sitemap item you want to link, but
      not the path. For example, a single jsp is used for 2 languages which have their own sitemap. You want a link to
      'contact' for English, and to 'kontakt' for Dutch. Using this attribute, you can link to a refId on the sitemap
      item. Both 'contact' and 'kontakt' should have the same refId then
    </description>
    <name>siteMapItemRefId</name>
    <required>false</required>
    <rtexprvalue>true</rtexprvalue>
    <type>java.lang.String</type>
  </attribute>
  <attribute>
    <description>If value is 'true' the created link will be a fully qualified link (URLs), thus starting with
      'http://' or 'https://' etc
    </description>
    <name>fullyQualified</name>
    <required>false</required>
    <rtexprvalue>true</rtexprvalue>
    <type>java.lang.Boolean</type>
  </attribute>
  <attribute>
    <description>If the link that is created should be the canonical link, use this attr with value true
    </description>
    <name>canonical</name>
    <required>false</required>
    <rtexprvalue>true</rtexprvalue>
    <type>java.lang.Boolean</type>
  </attribute>
  <attribute>
    <description>If the link should be created in the context of the current URL, use this attr with value true. When
      having canonical='true', this attribute is ignored.
    </description>
    <name>navigationStateful</name>
    <required>false</required>
    <rtexprvalue>true</rtexprvalue>
    <type>java.lang.Boolean</type>
  </attribute>
  <attribute>
    <description>Expert: Create a link for a mount with alias that has the value of this attribute. You can create
      cross-domain links with this, even to mounts having a different host name. Or to a mount belonging to REST
      calls.
    </description>
    <name>mount</name>
    <required>false</required>
    <rtexprvalue>true</rtexprvalue>
    <type>java.lang.String</type>
  </attribute>
  <attribute>
    <description>Expert: Create a link for a mount with type that has the value of this attribute. You can create
      cross-mode links with this, even to preview mount or live mount. Also, you can combine this with 'mount'
      attribute to create cross-domain links with specific type.
    </description>
    <name>mountType</name>
    <required>false</required>
    <rtexprvalue>true</rtexprvalue>
    <type>java.lang.String</type>
  </attribute>
  <attribute>
    <description>
      Whether or not to escape &amp;,&gt;,&lt;,", and ' to be safely used as a tag attribute (e.g, href, src, etc.) value.
      By default, this is set to true.
    </description>
    <name>escapeXml</name>
    <required>false</required>
    <rtexprvalue>false</rtexprvalue>
    <type>java.lang.Boolean</type>
  </attribute>
  <example><![CDATA[
  <!-- In a body component: A list of document names with summaries and links to those documents: -->

   <c:forEach var="child_document" items="${document_list}">
     <tr>
       <hst:link var="link" hippobean="${child_document}"/>
       <td class="title">
         <a href="${link}">${child_document.name}</a>
       </td>
       <td>${child_document.summary}</td>
     </tr>
   </c:forEach>

  <!-- In a <head>: -->

  <hst:link var='screencss' path='/css/community/screen.css'></hst:link>
  <link media='screen' href='${screencss}' type='text/css' rel='stylesheet'></link>

  <!-- In a menu: -->

   <ul id="nav-main">
     <c:forEach var="item" items="${menu.menuItems}">
       <c:choose >
         <c:when test="${! empty item.externalLink}">
           <li>
            <a href="${item.externalLink}"><b>${item.name}</b></a>
           </li>
         </c:when>
         <c:when test="${item.expanded}">
           <li class="active">
             ${item.name}
           </li>
         </c:when>
         <c:otherwise>
           <li>
             <hst:link var="link" link="${item.hstLink}" />
             <a href="${link}">
                 ${item.name}
             </a>
          </li>
         </c:otherwise>
       </c:choose>
     </c:forEach>
   </ul>

   <!-- Create a hst link for the current URL: -->
   <hst:link />
   OR
   <hst:link var="current"/> to store it in the var 'current'

   ]]></example>
</tag>