HST-2 Edge Side Includes Support
Introduction
HST provides basic ESI (Edge Side Includes) support for both external ESI Processors such as Content Delivery Networks (CDN) such as Akamai or Web Cache Servers such as Varnish, Squid or HST ESI Processor.
Edge Side Includes is a markup language for edge level dynamic web content assembly. The purpose of ESI is to tackle the problem of web infrastructure scaling. It is an application of edge computing. ESI Language Specification 1.0 was submitted to the World Wide Web Consortium (W3C) for approval in August 2001. Please find ESI Language Specification for your reference.
You can simply configure HST Components to be served as ESI markups instead of fully-rendered HTML markups. In this case, the ESI markups in the response will be processed by the external ESI Processor to replace the ESI markups by the fully retrieved HTML markups in the final phase.
In addition, HST ESI Pocessor is also able to process ESI markups by itself in the HST Container side even if you don't have an external ESI Processor in your infrastructure. HST Components can still serve ESI markups as an asynchronous HST Component, but the HST ESI Processor can process the ESI markups by itself to aggregate all together into the final response. Especially when you use HST Page Caching, you can leverage HST ESI Processing feature to improve performance by page caching while some parts of the cached pages can still be dynamically rendered and aggregated in the server side on each request.
How to Make Some HST Components Render ESI Markups?
An HST Page is built up from a tree of reusable HST Components. The trees of HST Components are managed in Hippo Repository.
First of all, you should mark an HST Component as asynchronous by turning on hst:async property. If you set an HST Component as asynchronous, then the HST Component and its descendants will be rendered asynchronously.
hst:async = true
The above configuration will result in asynchronously rendered HST Component window via client-side AJAX script calls by default.
See Asynchronous HST Components and Containers page for detail on asynchronous HST Components.
Now, asynchronous HST Components can also be rendered/aggregated in the server side by either an external ESI Processor or the built-in HST ESI Processor.
If you want to change the default AJAX asynchronous rendering behavior to ESI processing, then you should add the following property:
hst:asyncmode = esi
The default value of hst:asyncmode is ' ajax' if not defined.
If an HST Component is configured as asynchronous with ' esi' for hst:asyncmode, then the rendered markups of the HST Component window will be ESI markups in the first phase like the following example:
<esi:include src="http://example.org/news?_hn:type=component-rendering&_hn:ref=r1_r2" onerror="continue"/>
The ESI Include source is an HST Component Rendering URL, which invokes a specific HST Component window (having ' r1_r2' namespace) rendering instead of rendering the whole page.
So, the whole page response includes all the HTML markups for all the descendant HST Component windows except of ESI-based asynchronous HST Component window. The parts from the asynchronous HST Component windows will be ESI markups like the above example.
Now, the whole page can be processed by external ESI processors such as Akamai. The external ESI processor will invoke the ESI Include URL (e.g, http://example.org/news?_hn:type=component-rendering&_hn:ref=r1_r2) and replace the ESI markups by the retrieved HTML markups to serve the final page output to the clients.
HST ESI Processor
The HST can also be configured to run as an ESI processor, resolving Edge Side Includes markups. The HST ESI processing is seamlessly integrated with the HST Page Caching, making the HST capable of serving pages from cache and processing the Edge Side Includes markups dynamically on every request.
You can turn on the HST ESI Processor by adding the following property in /WEB-INF/hst-config.properties:
# Flag whether or not ESI fragments should be processed before writing output to client. esi.default.fragments.processing = true # Flag whether or not ESI processing only for async component. So, set it to false to enable manual ESI includes in templates. esi.processing.condition.async.components = false
Default ESI Include Elements for Asynchronous HST Component
For an ESI-based asynchronous HST Component, HST-2 Container renders a simple ESI Include element for the HST Component window like the following example, whether the ESI markups are processed by either an external ESI Processor or HST ESI Processor.
<esi:include src="http://example.org/news?_hn:type=component-rendering&_hn:ref=r1_r2" onerror="continue" />
When HST ESI Processor is turned on, the above ESI Include markup is processed by HST ESI Processor and replaced by the fully rendered HTML markups for the specific HST Component window.
Please note that you don't have to manually write ESI elements in your template pages in most cases. Just by marking an HST Component as ESI-based asynchronous component will do the trick.
However, if you want to add more ESI elements manually for some reason (e.g, in order to use other ESI elements than ESI Include elements), then you can do it as documented in the following section.
ESI Tags Supported by HST ESI Processor
However, an HST Component has a freedom to manually render ESI markups by itself without having to mark the HST Component as asynchronous. For example, the render template page (JSP, Freemarker, or whatever) of an HST Component can manually write ESI markups including the following ESI elements supported by HST ESI Processor:
- ESI Comment Blocks. e.g, <!--esi ... -->
- ESI Include Elements. e.g, <esi:include ... />
- ESI Comment Elements. e.g, <esi:comment ... />
- ESI Remove Elements. e.g, <esi:remove>...</esi:remove>
- ESI Variable Elements. e.g, <esi:vars>...</esi:vars>
So, the render template page can have the following example ESI markups:
<!--esi <h1>ESI Processing Enabled</h1> --> <esi:comment text="Related New Articles." /> <esi:include src="http://example.org/news?_hn:type=component-rendering&_hn:ref=r1_r2" onerror="continue" /> <esi:comment text="Include the license info or show a link." /> <!--esi <pre> <esi:include src="http://www.example.com/LICENSE"/> </pre> --> <esi:remove> <a href='http://www.example.com/LICENSE'>The license</a> </esi:remove> <esi:vars> <img src="http://www.example.com/$(HTTP_COOKIE{type})/hello.gif"/> <ul> <li>Accept Language: en? $(HTTP_ACCEPT_LANGUAGE{en})</li> <li>Host: $(HTTP_HOST)</li> <li>Referer: $(HTTP_REFERER)</li> <li>User Agent: $(HTTP_USER_AGENT{browser}), $(HTTP_USER_AGENT{version}), $(HTTP_USER_AGENT{os})</li> <li>Query String: $(QUERY_STRING{first}) $(QUERY_STRING{last})</li> </ul> </esi:vars>
Please refer to the ESI Specification for detail on how to use each ESI elements.
URLs Supported in ESI Include Tags by HST ESI Processor
HST ESI Processor supports only *local* HST URLs for the ESI Include tags. HST ESI Processor doesn't support external URLs or non-HST URLs for ESI Include tags.
So, the following URLs only can be supported by HST ESI Processor:
- HST Component Rendering URL which can be created by either HstResponse#createComponentRenderingURL() or <hst:componentRenderingURL /> tag.
- HST Resource URL which can be created by either HstResponse#createResourceURL() or <hst:resourceURL /> tag.
- HST Render URL which can be created by either HstResponse#createRenderURL() or <hst:renderURL /> tag.
As a simple example, the JSP template page of an HST Component can simply write an ESI Include element like the following example:
<esi:include src="<hst:componentRenderingURL/>" onerror="continue" />
The above example behaves the same as you simply mark the HST Component as ESI-based asynchronous HST Component. You can add more ESI elements manually for some reason though.
Limitations of HST ESI Processor
HST ESI Processor has the following limitations because it doesn't support all ESI elements like most existing external ESI Processors.
- As mentioned earlier, HST ESI Processor supports only *local* HST URLs. It does not support external URLs or non-HST URLs yet.
- HST Navigation URL (which can be created by either HstResponse#createNavigationalURL() or <hst:link /> tag) is NOT supported as ESI Included source URL yet.
- HST ESI Processor supports only "continue" value for the "onerror" attribute of <esi:include/> element. It doesn't support other values yet.
- HST ESI Processor does not support Surrogate-Capabilities header controls yet.
- HST ESI Processor does not support <esi:inline/>, <esi:choose>, <esi:when>, <esi:otherwise>, <esi:try> and <esi:attempt> tags yet.
.