This article covers a Hippo CMS version 7.7. There's an updated version available that covers our most recent release.

HST-2 URLs 

Introduction

The HST framework provides URL creation out-of-the-box. It takes care of including or excluding the contextPath, hence, should be used for every URL, also for static resources like css. This way, the HST application can be deployed with a contextPath, but does not show this contextPath in the URL. Combined with a single httpd rule the HST can serve any scheme (http/https), domain and port and can be deployed with any context (site in the httpd VirtualHost example below):

<VirtualHost  *:80>
  ProxyPreserveHost  On
  ProxyPass  / http://localhost:8080/site/
  ProxyPassReverse  / http://localhost:8080/site/
  ProxyPassReverseCookiePath  /site /
</VirtualHost>

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 linkrewriting to URLs for internal links between hippo Documents. The HST does this automatically, based on the configuration of the sitemap. It is the Request Matching reversed. For linkrewriting the HST supports by default:

  1. Cross Domain / Multi Site URLs : URLs between subsites, even with different domains

  2. Channel Aware URLs : mobile URLs stay within the mobile channels, while the URLs same content for the normal website stays within the website

  3. Context Aware URLs : URLs for one and the same document can be different according the context of the current URL

  4. 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)

  5. Preferred URLs : see [1]

  6. NavigationStateful URLs: see [1]

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

Creating a URL in a HstComponent:

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 = this.getContentBean(request);
       // 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 and for static resources. It automatically includes the contextPath in the URL when this is needed.

The <hst:link> tag takes an optional attr var in which the String output if stored. If the attr 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!

Creating a URL for a HippoBean

Assume you stored some document HippoBean's in documents, then the JSP for creating URLs for these documents is:

Creating a link in a JSP for a HippoBean:

<ul>
  <c:forEach var="document" items="${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:

Creating a link in a Freemarker template for a HippoBean:

<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, also see [1]

Creating a URL for a container resource, for example a CSS

Creating a link to a css:

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

Creating 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:

Creating a link to a repository binary:

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

Creating a URL to 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 example language:

Creating a link to a siteMapItemRefId:

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

Creating a URL for the currently 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 :

Creating a link for the currently matched sitemap item:

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

Creating a fullyQualified URL

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

Creating a fullyQualified link:

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

Creating 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? Really simple: If you use:

<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:

Creating a canonical link:

<hst:link hippobean="${document}" canonical="true"/>
<tag>
        <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>
        <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>
        <attribute>
            <name>var</name>
            <required>false</required>
            <rtexprvalue>false</rtexprvalue>
            <type>java.lang.String</type>
            <description>The variable name of the link tag</description>
        </attribute>
        <attribute>
            <name>link</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
            <type>org.hippoecm.hst.core.linking.HstLink</type>
            <description>A HstLink object, containing a already rewritten object</description>
        </attribute>
        <attribute>
            <name>path</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
            <type>java.lang.String</type>
            <description>A string path, typically a location relative to the webapp</description>
        </attribute>
        <attribute>
            <name>subPath</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
            <type>java.lang.String</type>
            <description>A string subPath which gets appended to the path with a delimiter './' . This makes it useful for creating REST links</description>
        </attribute>
        <attribute>
            <name>hippobean</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
            <type>org.hippoecm.hst.content.beans.standard.HippoBean</type>
            <description>A HippoBean object. This is typically one of your bean mapped
            objects</description>
        </attribute>
        <attribute>
            <name>siteMapItemRefId</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
            <type>java.lang.String</type>
            <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>
        </attribute>
        <attribute>
            <name>external</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
            <type>java.lang.Boolean</type>
            <description>Deprecated: use fullyQualified instead.
            If value is 'true' the created link will be a fully qualified link (URLs), thus starting with
                'http://' or 'https://' etc</description>
        </attribute>
        <attribute>
            <name>fullyQualified</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
            <type>java.lang.Boolean</type>
            <description>If value is 'true' the created link will be a fully qualified link (URLs), thus starting with
                'http://' or 'https://' etc</description>
        </attribute>
        <attribute>
            <name>canonical</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
            <type>java.lang.Boolean</type>
            <description>If the link that is created should be the canonical link, use this attr with value true</description>
        </attribute>
        <attribute>
            <name>navigationStateful</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
            <type>java.lang.Boolean</type>
            <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>
        </attribute>
        <attribute>
            <name>mount</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
            <type>java.lang.String</type>
            <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>
        </attribute>
        <attribute>
            <name>mountType</name>
            <required>false</required>
            <rtexprvalue>true</rtexprvalue>
            <type>java.lang.String</type>
            <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>
        </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>