11 Caching Dynamic Content with ESI Language Tags

This chapter describes the Edge Side Includes (ESI) tags provided for content assembly of dynamic fragments.

ESI is an open specification co-authored by Oracle. Its purpose is to develop a uniform programming model to assemble dynamic pages in a dynamic content cache deployed as a surrogate or proxy between clients and origin servers.

ESI is an XML-like markup language that enables dynamic content assembly of fragments by Oracle Web Cache. A template page is configured with ESI markup tags that fetch and include dynamic HTML fragments. The fragments themselves can also contain ESI markup. You can assign caching rules to the template page and HTML fragments. By enabling page assembly in Oracle Web Cache rather than in the origin server, you can increase cache hit rates and improve performance.

This chapter includes the following topics:

See http://www.esi.org for the ESI language release 1.0 specification.

11.1 Introduction to ESI for Partial Page Caching

Oracle Web Cache provides dynamic assembly of Web pages with both cacheable and non-cacheable page fragments. It provides for assembly by enabling Web pages to be divided into fragments of differing caching profiles. These fragments are maintained as separate elements in the cache. The fragments are assembled into HTML pages as appropriate when requested by end users.

By enabling dynamic assembly of Web pages on Oracle Web Cache rather than on the origin servers, you can choose to cache some fragments of assembled pages. With partial page caching, much more HTML content can be cached, and then assembled and delivered by Oracle Web Cache when requested. Furthermore, page assembly can be conditional, based on information provided in HTTP request headers or end-user cookies.

The basic structure that an application developer uses to create content for partial-page caching is a template page containing fragments. As depicted in Figure 11-1, the template consists of common elements, such as a logo, navigation bars, framework, and other "look and feel" elements of the page. The fragments represent dynamic subsections of the page.

Figure 11-1 Template Page

Description of Figure 11-1 follows
Description of "Figure 11-1 Template Page"

The template page is associated with the URL that end users request. To include the fragments, the template page is configured with ESI markup tags that instruct Oracle Web Cache to fetch and include the HTML fragments. The fragments themselves are HTML files containing discrete text or other objects.

Each included fragment is a separate object with its own caching policy. Content providers may want to cache the template for several days, but only cache a particular fragment, such as an advertisement or stock quote, for a matter of seconds or minutes. Other fragments (such as a user's bank account total) may be declared non-cacheable.

Table 11-1 provides a summary of the main ESI tags.

Table 11-1 Summary of ESI Tags

Tag Description

<esi:choose>

Performs conditional processing based on Boolean expressions

<esi:comment>

Specifies comments not be included in the output

<esi:environment>

Allows variable access from an HTTP response

<esi:include>

Includes an HTML fragment

<esi:inline>

Marks a fragment as a separately cacheable fragment, embedded in the HTTP response of another object

<esi:invalidate>

Specifies an invalidation request within the response of a browser page

<esi:remove>

Specifies non-ESI markup if ESI processing is not enabled

<esi:try>

Specifies alternate processing when a request fails because the origin server is not accessible

<esi:vars>

Permits variable substitution for environment variables


Example 11-1 shows the ESI markup language for the template page shown in Figure 11-1.

Example 11-1 ESI Markup

<HTML>
<HEAD>
<TITLE>
Company.com
</TITLE>
</HEAD>
<BODY>
...
<!-- The following <esi:comment> tags are removed if this page is processed by an ESI processor. -->

<!--esi

 <esi:comment text="This is the HTML source when ESI is enabled." />

 <esi:comment text="Start: The quick link section. You cannot use the standard
 HTML comments because the end of that comment tag would disrupt the HTML comment
tag with 'esi' following the two '-'." />

 <esi:comment text="The URI query string parameter 'sessionID' is used to carry
session identifiers, The session ID is encoded in all links." />

 <esi:comment text="'Profile' refers to environment variables stored in
 GetProfile.jsp. GetProfile.jsp enables access to 'PersonalInterest.' 'zipcode,'
 'tickers,' and 'address' environment variables." />

 <esi:environment src="/GetProfile.jsp?sessionID=$(QUERY_STRING{sessionID})"
name="Profile" />

<esi:vars>
   <A HREF="/shopping.jsp?sessionID=$(QUERY_STRING{sessionID})">
     <IMG SRC="/img/shopping.gif">
   </A>
   <A HREF="/news.jsp?sessionID=$(QUERY_STRING{sessionID})">
     <IMG SRC="/img/news.gif">
   </A>
   <A HREF="/sports.jsp?sessionID=$(QUERY_STRING{sessionID})">
     <IMG SRC="/img/sports.gif">
   </A>
   <A HREF="/fun.jsp?sessionID=$(QUERY_STRING{sessionID})">
     <img src="/img/fun.gif">
  </A>
  <A HREF="/about.jsp?sessionID=$(QUERY_STRING{sessionID})">
     <iMG SRC="/img/about.gif">
   </A>
 </esi:vars>

 <esi:comment text="End: The quick link section" />
...
 <H3>Local Weather</H3>
 <esi:include src="/weather.jsp?sessionID=$(QUERY_STRING{sessionID})&zipcode=$(Profile{zipcode})" />
...

 <H3>Stock Quotes</H3>
 <esi:try>
   <esi:attempt>
     <esi:include src="/CompanyStock.jsp?sessionID=$(QUERY_ STRING{sessionID})&tickers=$(Profiles{tickers})" />
   </esi:attempt>
   <esi:except>
     The company stock quote is temporarily unavailable.
   </esi:except>
 </esi:try>
...
 <H3>What's New at Company</H3>
 <!-- This section is a static file that does not carry session information -->
 <esi:include src="/whatisnew.html" />

...

 <H3>Today's News</h3>
 <esi:choose>

   <esi:when test="$(Profile{PersonalInterests}) == 'Sports'">
     <H4>Sport News</H4>
     <esi:include src="/SportNews.jsp?sessionID=$(QUERY_STRING{sessionID})" />
   </esi:when>

   <esi:when test="$(Profile{PersonalInterests}) == 'Career'">
     <H4>Financial News</H4>
     <esi:include src="/FinancialNews.jsp?sessionID=$(QUERY_STRING{sessionID})" />
   </esi:when>

   <esi:otherwise>
     <H4>General News</H4>
     <esi:include src="/DefaultNews.jsp?sessionID=$(QUERY_STRING{sessionID})" />
   </esi:otherwise>

 </esi:choose>

...

-->

<!-- This is the HTML source when ESI is disabled. -->
<esi:remove>
Alternative HTML source that does not use ESI goes here. This tag enables you 
to disable ESI on the fly without redeveloping or redeploying a different version
 of the page. 
</esi:remove>
...
</BODY>
</HTML>

Example 11-2 shows the XML response of GetProfile.jsp, which provides access to profile environment variables.

Example 11-2 GetProfile.jsp XML Response

<?xml version=1.0?>
<esi:environment esiversion="ORAESI/9.0.4">
  <PersonalInterests>Sports</PersonalInterests>
  <zipcode>94065</zipcode>
  <tickers>ORCL,YHOO</tickers>
  <address>500 Oracle Parkway, Redwood Shores, CA 94065</address>
</esi:environment>

11.1.1 ESI Features

ESI can be used with HTML, XML, JSP, ASP, and any Web programming technology. The ESI language includes the following features:

  • Inclusion

    An ESI processor assembles HTTP or HTTPS fragments of dynamic content, retrieved from the network, into aggregate pages to output to the user. Each fragment can have its own caching rules.

  • Support of variables

    ESI supports the use of variables based on HTTP request attributes, as well as custom variables from included HTML fragments. Variables can be used by ESI statements during processing or can be output directly into the processed markup.

  • Conditional processing

    ESI allows use of Boolean comparisons for conditional logic in determining how pages are processed.

  • Error handling and alternative processing

    Some ESI tags support specification of a default resource or an alternative resource, such as an alternate Web page, if the primary resource cannot be found. Further, it provides an explicit exception-handling statement block.

  • Character set conversion

    ESI fragments in different character sets are converted to one character set. This way, all partial pages are assembled in a fixed character set. Character set conversion works in the following manner:

    1. Oracle Web Cache receives a request for a template page.

    2. Oracle Web Cache fetches the fragments, and converts all of the fragments to the template's character set. The default character set is ISO-8859-1.

    Oracle Web Cache does not perform character set conversion for non-ESI pages.

  • XML conversion to HTML

    Oracle Web Cache uses XSL Transformations (XSLT) to transform XML fragments into HTML.

11.1.1.1 ESI for Java (JESI)

Oracle Web Cache provides the JESI tag library as a convenient interface to ESI tags and functionality. In addition, you can deploy the JESI tag library on Oracle WebLogic Server. Developers have the option of using ESI tags directly in any Web application, but JESI tags provide additional convenience in a JSP environment.

Because ESI and JESI are open standards, you can use the JESI tag library in any standard JSP environment if an ESI processor, such as Oracle Web Cache, is available.

Even though JSP developers can always use ESI, JESI provides an even easier way for JSP developers to express the modularity of pages and the cacheability of those modules, without requiring developers to learn a new syntax.

For further information about using JESI with Oracle WebLogic Server, see:

http://www.oracle.com/technology/sample_code/tech/java/codesnippet/webcache/index.html

11.1.2 ESI Language Elements in the Surrogate-Control Response Header

Oracle Web Cache supports the ESI language tags, elements, and attributes listed in Table 11-2. The rightmost column specifies, for each ESI tag, attribute, or element, all the feature sets that support it. For example, the <esi:invalidate> tag is only supported by the "ESI-INV/1.0" feature set. To enable the correct processing in Oracle Web Cache, specify all the feature sets that an ESI template uses in the content control directive of the Surrogate-Control response header. However, you do have to specify features sets used within an ESI fragment directly or indirectly included in the template. For example, if an ESI template uses an <esi:invalidate> and an <esi:environment> tag with an <esi:log> element, the content control directive must include "ESI-INV/1.0" and "ORAESI/9.0.4", as follows:

Surrogate-Control: content="ESI-INV/1.0 ORAESI/9.0.4"

See Section 6.10 for further information about configuring the Surrogate-Control response header.

Table 11-2 ESI Language Features

ESI Language Feature See Also content="value" Control Directive in Surrogate-Control Response Header Supporting Feature

<esi:choose> | <esi:when> | <esi:otherwise> tags

Section 11.4.1

"ORAESI/9.0.4"

"ORAESI/9.0.2"

"ESI/1.0"

<esi:comment> tag

Section 11.4.2

"ORAESI/9.0.4"

"ORAESI/9.0.2"

"ESI/1.0"

<esi:environment> tag

Section 11.4.3

"ORAESI/9.0.4"

"ORAESI/9.0.2"

<esi:include> tag

Section 11.4.4

"ORAESI/9.0.4"

"ORAESI/9.0.2"

"ESI/1.0"

<esi:environment> tag and <esi:include> tag attributes and elements

 

 

alt attribute

Section 11.4.4

"ORAESI/9.0.4"

"ESI/1.0"

max-age attribute

Section 11.4.4

Section 11.4.3

"ORAESI/9.0.4"

"ORAESI/9.0.2"

onerror attribute

Section 11.4.4

"ORAESI/9.0.4"

"ORAESI/9.0.2"

"ESI/1.0"

src attribute

Section 11.4.4

"ORAESI/9.0.4"

"ORAESI/9.0.2"

"ESI/1.0"

timeout attribute

Section 11.4.4

Section 11.4.3

"ORAESI/9.0.4"

"ORAESI/9.0.2"

<esi:log> element

Section 11.4.4

Section 11.4.3

"ORAESI/9.0.4"

<esi:request_header> element

Section 11.4.4

Section 11.4.3

"ORAESI/9.0.4"

"ORAESI/9.0.2"

<esi:request_body> element

Section 11.4.4

Section 11.4.3

"ORAESI/9.0.4"

"ORAESI/9.0.2"

<esi:inline> tag

Section 11.4.5

"ORAESI/9.0.4"

"ORAESI/9.0.2"

"ESI-Inline/1.0"

"ESI/1.0"

name attribute

Section 11.4.5

"ORAESI/9.0.4"

"ORAESI/9.0.2"

"ESI-Inline/1.0"

"ESI/1.0"

fetchable attribute

Section 11.4.5

"ORAESI/9.0.4"

"ORAESI/9.0.2"

"ESI-Inline/1.0"

"ESI/1.0"

max-age attribute

Section 11.4.5

"ORAESI/9.0.4"

"ORAESI/9.0.2"

timeout attribute

Section 11.4.4

Section 11.4.3

"ORAESI/9.0.4"

"ORAESI/9.0.2"

<esi:invalidate> tag

Section 11.4.6

"ESI-INV/1.0"

<esi:remove> tag

Section 11.4.7

"ORAESI/9.0.4"

"ORAESI/9.0.2"

"ESI/1.0"

<esi:try> | <esi:attempt> | <esi:except> tags

Section 11.4.8

"ORAESI/9.0.4"

"ORAESI/9.0.2"

"ESI/1.0"

<esi:vars> tag

Section 11.4.9

"ORAESI/9.0.4"

"ORAESI/9.0.2"

"ESI/1.0"

<!--esi...---> tag

Section 11.4.10

"ORAESI/9.0.4"

"ORAESI/9.0.2"

"ESI/1.0"


See http://www.esi.org/spec.html for the ESI Language Specification 1.0 and the Edge Architecture Specification.

11.1.3 About the Surrogate-Control Response Header and Surrogate-Capability Request Header for Cached Objects

To enable Oracle Web Cache to process ESI tags, you set an HTTP Surrogate-Control response-header field in the HTTP response message of the pages that use ESI tags.

Surrogate-Control: content="ESI-INV/1.0 ORAESI/9.0.4"

For each requested object from the cache, Oracle Web Cache appends a Surrogate-Capability request-header field to an object's HTTP request message. The Surrogate-Capability request-header serves the following purposes:

  • Enables applications to detect Oracle Web Cache

  • Identifies the types of ESI operations that Oracle Web Cache can perform

The Surrogate-Capability request-header enables Oracle Web Cache to identify the operations it can perform to origin servers acting as caches. The Surrogate-Capability request-header field supports the following syntax:

Surrogate-Capability: orcl="operation_value operation_value ..."

where "operation_value" is one or more of the following:

  • "ORAESI/9.0.4" to process ESI tags with Oracle-proprietary additions for content assembly and partial page caching. "ORAESI/9.0.4" supports all the ESI tags provided by Oracle Web Cache in 10g (9.0.4) and later releases.

  • "ORAESI/9.0.2" to process ESI tags with Oracle proprietary additions for content assembly and partial page caching. "ORAESI/9.0.2" supports all the ESI tags provided by Oracle Web Cache in Release 2 (9.0.2 and 9.0.3).

  • "ESI/1.0" to process standard ESI tags for content assembly and partial page caching

  • "ESI-Inline/1.0" to process <esi:inline> tags

  • "ESI-INV/1.0" to process <esi:invalidate> tags

  • "webcache/1.0" to process the <!-- WEBCACHETAG--> and <!-- WEBCACHEEND--> tags for personalized attributes

The values "ORAESI/9.0.2", "ESI/1.0", and "ESI-Inline/1.0" are subsets of "ORAESI/9.0.4". For this release, you specify only "ORAESI/9.0.4" for ESI assembly, "ESI-INV/1.0" for inline invalidation, or "webcache/1.0" for personalized attributes.

See Table 11-3 or further information about the ESI tags supported for each operation_value.

11.1.4 Syntax Rules

ESI elements and attributes adhere to XML syntax but can be embedded in other objects, such as HTML or XML objects. When Oracle Web Cache processes the page, the ESI elements themselves are stripped from the output.

ESI syntax generally adheres to XML syntax rules. Keep the following in mind when using the tags:

  • ESI tags and attributes are case sensitive.

    They are generally lowercase.

  • Supported CGI environment variables are case sensitive.

    They are generally uppercase.

  • ESI does not support the use of whitespace next to the equal sign (=) or between the "<" and "esi:"

    The following shows an invalid construction:

    <esi:include src = "www.foo.com"/>
    

The following shows the correct form:

<esi:include src="www.foo.com"/>

11.1.5 Nesting Elements

As shown in Example 11-3, an ESI tag can contain nested ESI elements and other HTML markup.

Example 11-3 Nested ESI Elements

<esi:choose>
  <esi:when test="$(HTTP_HOST) == 'www.company.com'">
    <esi:include src="/company.html" />
    <h4>Another</h4>
    <esi:include src="/another.html" />
  </esi:when>
  <esi:when test="$(HTTP_COOKIE{fragment) == 'First Fragment'">
    <esi:try>
      <esi:attempt>
        <esi:include src="/fragment1.html" />
      </esi:attempt>
      <esi:except>
        <esi:choose>
          <esi:when test="$(HTTP_COOKIE{otherchoice}) == 'image'" >
            <img src="/img/TheImage.gif">
          </esi:when>
          <esi:otherwise>
            The fragment is unavailable.
         </esi:otherwise>
        </esi:choose>
      </esi:except>
    </esi:try>
  </esi:when>
  <esi:otherwise>
   The default selection.
  </esi:otherwise>
</esi:choose>

11.1.6 Variable Expressions

ESI supports the HTTP request variables and environment variables used with the <esi:environment> tag.

This section contains the following topics:

See Section 11.4.3 for instructions on including custom variables

11.1.6.1 Variable Usage

To refer to a variable, prefix it with a dollar sign and surround the variable name with parentheses:

$(VARIABLE_NAME)

For example:

$(HTTP_HOST)

Variables are accessed by a key as follows:

$(VARIABLE_NAME{key})

To access a variable's substructure, append the variable name with braces containing the key which is being accessed. For example:

$(HTTP_COOKIE{username})

The key is case sensitive and optional. If a key is not specified, the environment variable returns the whole content of the environment fragment. Oracle advises specifying an environment variable without a key only for testing whether the environment is empty. In the following ESI markup, $(logindata) is a variable that is evaluated against a null value:

<esi:environment src="/getlogindata" name="logindata"/>
<esi:include src="/login/$(logindata{account})"/">
<esi:choose>
  <esi:when test="$(logindata) != null">
    <esi:include src="/login/$(logindata{account})"/>
 </esi:when>
 <esi:otherwise>
   <esi:include src="/login/guest.html"/>
 <esi:otherwise>
</esi:choose>  

11.1.6.2 Variable Default Values

You can use the logical OR (|) operator to specify a default value in the following form:

$(VARIABLE|default)

A variable takes the default value only when the variable or its key does not exist. If it evaluates to an empty string, the empty string is returned, not the default value.

The following example results in Oracle Web Cache fetching http://example.com/default.html if the cookie id is not in the request:

<esi:include src="http://example.com/$(HTTP_COOKIE{id}|default).html"/>

As with other literals, if whitespace must be specified, the default value must be single-quoted. For example:

$(HTTP_COOKIE{first_name}|'new user')

Note:

HTTP_HOST and HTTP_REFERER do not support default values.

11.1.6.3 HTTP Request Variables

Table 11-3 lists the HTTP request variables supported by ESI. Note the following:

  • Except for QUERY_STRING, the values for the variables are taken from HTTP request-header fields. In the case of QUERY_STRING, the value is taken from either the HTTP request body or the URL.

  • Variables are only interpreted when enclosed within ESI tags.

  • Variables with a substructure type of List or Dictionary are accessed by a key.

  • Variables identified with a substructure type of Dictionary make access to strings available through their appropriate keys.

  • Dictionary keys are case sensitive.

  • Variables identified with a substructure type of List return a Boolean value depending on whether the requested value is present.

Table 11-3 HTTP Request Variables Supported by ESI

Variable Name HTTP Header Field Substructure Type/Variable Type Description Example

$(HTTP_ACCEPT_LANGUAGE{language})

Accept-Language request-header field

Specifies the set of languages that are preferred as a response. The language is used as the key.

List/Boolean

Specifies the language to use as the key and evaluates to the language specified in the HTTP request header

Variable Setting:

$(HTTP_LANGUAGE{en-gb})

HTTP Request Header Contains:

Accept_Language:en-gb

Result: Returns en-gb.

$(HTTP_COOKIE{cookie})

Set-Cookie response-header field or Cookie request-header field

Specifies cookie name and value pairs. A cookie name is used as the key.

If the Cookie request-header and Set-Cookie response-header have different values for the same cookie name, the name value pair from the Set-Cookie response header is used.

Dictionary/String

Specifies the cookie name to use as the key and returns that cookie's value

Variable Setting:

$(HTTP_COOKIE{visits})

HTTP Request Header Contains:

Cookie:visits=42

Result: Returns 42.

$HTTP_HEADER{header})

Any HTTP request header

Dictionary/String

Specifies an HTTP request header name to use as the key and returns that header's value

Variable Setting:

$(HTTP_HEADER{Referer})

HTTP Request Header Contains:

Referer: http://www.company.com:80

Result: Returns

http://www.company.com:80

$HTTP_HOST

Host request-header field

Specifies the host name and port number of the resource. Port 80 is the default port number.

Not Applicable/String

Returns the value of the HOST header

Variable Setting:

$(HTTP_HOST)

HTTP Request Header Contains:

Host:http://www.company.com:80

Result: Returns

http://www.company.com:80

$HTTP_REFERER

Referer request-header field

Specifies the URL of the reference resource

Not Applicable/String

Returns the value of the REFERER header

Variable Setting:

$(HTTP_REFERER)

HTTP Request Header Contains:

Referer: http://www.company.com:80

Result: Returns

http://www.company.com:80

$(HTTP_USER_AGENT{browser})

$HTTP_USER_AGENT{version})

$HTTP_USER_AGENT{os})

User-Agent request-header field

Specifies the Web browser type, browser version, or operating system that initiated the request.

Dictionary/String

Specifies one of three keys: browser for browser type, version for browser version, and os for operating system

Variable Setting:

$(HTTP_USER_AGENT{browser})

HTTP Request Header Contains:

User-Agent:Mozilla/4.0 (compatible, MSIE 5.5, Windows)

Result: Returns MSIE

$(HTTP_USER_AGENT{version})

Result: Returns 4.0.

$(HTTP_USER_AGENT{os})

Result: Returns Windows

$(QUERY_STRING{parameter})

Not Applicable

Dictionary/String

Given a parameter name in a query string, returns the value of the parameter without URL encoding. The query string can be in an URL or a request body.

See Also: http://www.rfc-editor.org/ for further information about URL encoding.

Variable Setting:

$(QUERY_STRING{CEO})

Query Request Contains:

CEO=Jane%20Doe&CFO=John%20Doe

Result: Returns the value of fullname decoded. In this example, CEO returns a value of Jane Doe.

$(QUERY_STRING)

Not Applicable

Not Applicable/String

Specifies to return the entire query string encoded

Variable Setting:

$(QUERY_STRING)

Query Request Contains:

CEO=Jane%20Doe&CFO=John%20Doe

Result: Returns the entire query string encoded:

CEO=Jane%20Doe&CFO=John%20Doe

$(QUERY_STRING_ENCODED{parameter})

Not Applicable

Dictionary/String

Given a parameter name in a query string, returns the value of the parameter with URL encoding. The query string can be in an URL or a request body.

Variable Setting:

$(QUERY_STRING{fullname})

Query Request Contains:

fullname=Jane%20Doe

Result: Returns the value of fullname encoded:

Jane%20Doe

$(QUERY_STRING_ENCODED)

Not Applicable

Not Applicable/String

The same as $(QUERY_STRING)

Variable Setting:

$(QUERY_STRING_ENCODED)

Query Request Contains:

fullname=Jane%20Doe

Result: Returns the entire query string encoded:

fullname=Jane%20Doe

$(QUERY_STRING_DECODED{parameter})

Not Applicable

Dictionary/String

The same as $(QUERY_STRING{parameter})

Variable Setting:

$(QUERY_STRING_DECODED{CEO})

Query Request Contains:

fullname=Jane%20Doe

Result: Returns the value of fullname decoded. In this example, fullname returns a value of Jane Doe.


11.1.7 Exceptions and Errors

ESI uses several mechanisms to handle exceptions encountered during an ESI fragment request. In a given situation, you can make use of all mechanisms simultaneously, or use one at a time, depending on the business logic you are developing.

The first mechanism is found in the ESI language, which provides three specific elements for fine-grain control over content assembly in error scenarios:

  • The alt attribute of the <esi:include> tag

  • The onerror attribute of the <esi:include> tag

  • The try |attempt |except block

  • Default page for the fragment

When the fragment specified for the src attribute of the <esi:include> tag cannot be fetched, the fragment specified with the alt attribute is used as an alternative. If the alt attribute is not used or the fragment cannot be fetched, the onerror attribute is used. The onerror attribute is used before the try |attempt |except block. If the try |attempt |except block does not exist, the exception handling is propagated to the parent or template page. If all the ESI language controls fail, Oracle Web Cache displays a default page for the fragment.

See the following sections:

11.1.8 About Fragmentation with the Inline and Include Tags

The <esi:inline> and <esi:include> tags enable applications to adopt ESI page fragmentation and assembly. The following sections describe the tags and explain when the tags are appropriate to use.

11.1.8.1 Using Inline for Non-Fetchable Fragmentation

Most existing applications are only designed to output an entire Web page to HTTP requests. These fragments and templates are non-fetchable, meaning they are not to be fetched independently from the origin server. If a cache needs any of these fragments or templates, the corresponding full Web page must be requested. To use ESI page assembly for non-fetchable fragments, an application can output the full page response just as it does normally, with the exception that at the beginning and the end of each fragment, an <esi:inline> tag is inserted with a fragment name to demarcate the fragment. Oracle Web Cache stores the enclosed portions as separate fragments and the original page as a page template without the enclosed fragments. Fragments are shared among templates if their names are identical and they are from the same site.

Example 11-4 shows a simple <esi:inline> example. The HTML table enclosed by the <esi:inline> tag is the fragment content. The area preceding <esi:inline name="/news101"> and the area following </esi:inline> form the page template. If another page contains an <esi:inline> tag with the same name "/news101", the two fragments logically share the same content.

Example 11-4 Inline Non-Fetchable Example

<HTML>
...
<esi:inline name="/news101">
<TABLE>
...
</TABLE>
</esi:inline>
...
</HTML>

When an application uses non-fetchable <esi:inline> fragments, the full page must be requested for every cache miss. At first, it can appear that there is no apparent cache benefit for cache misses. However, non-fetchable <esi:inline> fragments improves overall caching by:

  • Increasing the cache hit ratio

    Because shared fragments can be extracted into separate fragments, the size of the dynamic portion is reduced. A reduced space requirement results in a higher cache hit ratio than full page caching.

  • Reducing cache update frequency

    Dynamic shared fragments require only one update. For example, a shared stock market fragment may expire much more frequently than any other parts of the page. With <esi:inline> fragmentation, only one cache update of any full page containing this fragment is enough to bring all full pages sharing this fragment current. Therefore, even non-fetchable <esi:inline> fragments can significantly reduce cache update frequency. The cost reduction is proportional to the degree of sharing.

To invalidate non-fetchable fragments, you must invalidate both the template object and the non-fetchable fragments to ensure the fragments are invalidated.

11.1.8.2 Using Inline for Fetchable Fragmentation

<esi:inline> fragments are by default non-fetchable. If an application supports independently fetchable fragments, it is possible to use the <esi:inline> for fetchable fragments by setting the fetchable attribute to yes.

Example 11-5 shows an <esi:inline> example with a fetchable fragment named /news101. A request for the page returns the template page and the fetchable fragment.

Example 11-5 Inline Fetchable Example

<HTML>
...
<esi:inline name="/news101" fetchable="yes">
<TABLE>
...
</TABLE>
</esi:inline>
...
</HTML>

See Section 11.1.8.2 for further information about the fetchable attribute.

11.1.8.3 Using Include for Fragmentation

The <esi:include> tag is another way to define fragments and templates in an HTTP output for dynamic content caching and assembly. It is in many ways similar to the <esi:inline> tag. It defines a name for the defined fragment. The page including an <esi:include> tag is a template that references the defined fragment. However, it also has some key differences which make its applicable scenarios very different from those of <esi:inline>:

  • An <esi:include> tag in a template only defines the reference to a fragment.

    It does not enclose an embedded fragment directly in the template. As a result, a template with <esi:include> tags can be applied to multiple users. In contrast, a template with embedded <esi:inline> tags must be unique to each user.

  • A fragment referenced by an <esi:include> tag must always be independently fetchable by HTTP or HTTPS.

    The requested URL equals the fragment name. In contrast, an <esi:inline> tag's name only identifies the uniqueness of the fragment and is not used to fetch the actual content. The attribute defining the fragment name in <esi:include> fragment is src instead of name.

There are at least two scenarios where using <esi:include> tags is beneficial:

  • Some applications, such as a Web portal, naturally assemble content from external sources. The application only provides a template that is used to fetch various fragments from third-party sources. In this case, the <esi:include> tags fetch and assemble directly, reducing one layer of redundancy.

  • Some applications offer faster responses for template-only requests than full-page requests that use <esi:inline> tags. If <esi:include> is used for page fragmentation and assembly, Oracle Web Cache can miss only on the templates when most or all fragments are already cached, saving effective cache miss cost. In many cases, it is also valuable to cache the personalized templates because these seldom change.

Example 11-1 shows ESI markup with <esi:include> tags.

11.1.8.4 Selecting the Fragmentation Mechanism for Your Application

Although both <esi:include> and <esi:inline> enable Oracle Web Cache to fetch fragments for the client browser, <esi:include> is more robust for performing this task and provides an easy way in which to manage fragments. Because <esi:include> affects the application flow, it is best to incorporate <esi:include> early in the design phase of an application. For an existing application, <esi:inline> is better mechanism because it requires minimal change to your application.

11.1.9 Referer Request-Header Field

When Oracle Web Cache receives a client request for a template page with a Referer request-header field, it forwards the request with the Referer request header to the origin server. In turn, the origin server returns fragments to Oracle Web Cache with the URL of the template as the value for the Referer header. This functionality associates the fragment request with the template request.

11.1.10 Cookie Management for Template Pages and Fragments

Session cookie establishment for ESI templates and fragments works much the same way as typical Oracle Web Cache objects with the following additional features:

  • Cookie request-header field inheritance

    When a client requests an ESI template page that includes fragments, requests for fragment pages are generated in Oracle Web Cache. A fragment request inherits the Cookie request-header field from the template request if the value of the Host request-header field matches the value of Host request-header field in the template request.

  • Set-Cookie response-header field accumulation

    When assembly of fragments is complete, Oracle Web Cache includes a Set-Cookie response-header field in the response with the cookie information from the template. For those fragments with a Host request-header field that matches the Host request-header field in the template, Oracle Web Cache also accumulates the Set-Cookie response-header fields with that of the template. For those fragments with a Host request-header field that does not match the Host request-header field in the template, Oracle Web Cache does not accumulate the Set-Cookie response-header field with that of the template and other matching fragments.

See Section 11.1.6 for a description of how you can use the HTTP_COOKIE variable in ESI markup.

11.2 Enabling Dynamic Assembly of Content and Partial Page Caching

For an overview of partial page caching, see Section 11.1.

This section describes how to enable dynamic assembly of Web pages with fragments and how to create rules for the cacheable and non-cacheable page fragments. It contains the following topics:

11.2.1 Enabling Partial Page Caching

To enable partial page caching:

  1. Configure the template page as follows:

    1. Use ESI markup tags in the template to fetch and include the fragments.

      Important:

      ESI tags cannot be used on a page that contains <!-- WEBCACHETAG--> and <!-- WEBCACHEEND--> tags. If you require simple personalization and are using ESI, see Section 11.2.2, "Using ESI for Simple Personalization".
    2. In the template page, configure the HTTP response with the Surrogate-Control response-header field. For example:

      Surrogate-Control: max-age=30+60, content="ORAESI/9.0.4"
      
    3. If the Surrogate-Control response-header field does not include all the caching attributes required for the template page, create a caching rule for the page.

  2. Configure the fetchable fragments:

    • Use a Surrogate-Control response-header field in the HTTP response message.

    • If the Surrogate-Control response-header field does not include all the caching attributes required for the fragment, create a caching rule for the fragment.

For more information, see:

  • Section 11.4 for further information about ESI markup tags

  • Section 6.10 for further information about configuring the Surrogate-Control response-header field

  • Section 6.8 for further information about configuring caching rules

11.2.2 Using ESI for Simple Personalization

You can use variable expressions for simple personalization.

For example, the following HTML substitutes a user's name based on the value the client browser passes with username cookie. In addition, the session information contained within the sessionID cookie is used to replace session information for one user with another user.

The same effect is achieved with the following ESI markup:

<esi:vars>
 Welcome $(HTTP_COOKIE{'username'})!
 Here is a <A HREF="/jsp/myPage.jsp?sessionID=$(QUERY_STRING{'sessionid'})">link</A>.
</esi:vars>        

The <esi:vars> tag enables you to use an ESI environment variable outside of an ESI tag. You can also use variables with other ESI tags.

See the following sections:

11.2.3 Examples of ESI Usage

This section provides examples of ESI usage in the following topics:

11.2.3.1 Example of a Portal Site Implementation

Figure 11-2 shows a portal site response page, http://www.company.com/servlet/oportal?username=Mark, for a registered user named Mark.

Figure 11-2 Portal Site Page

Description of Figure 11-2 follows
Description of "Figure 11-2 Portal Site Page"

This page is assembled by Oracle Web Cache. A template page configured with ESI markup tags for a personalized greeting, weather, stocks, promotional advertisement, news, and sports fragments is assembled based on Mark's preferences. For example, because Mark chose San Francisco weather, the application looks up San Francisco weather information and puts it into the final full HTML page output. Because of its dynamic content, this page would not be cacheable. On the other hand, with ESI markup tags, Oracle Web Cache assembles and caches most of the content.

The following sections describe how the template page and its fragments are implemented using <esi:inline> and <esi:include> tags:

11.2.3.1.1 Portal Example Using inline Tags

This section describes how <esi:inline> tag fragmentation and assembly can drastically increase the value of dynamic content caching for pages that do not contain real-time elements. It shows how to apply the <esi:inline> tag for an existing application that supports non-fetchable fragments. The <esi:inline> tag helps reduce space consumption and improves cache hit ratios by isolating the dynamic content.

Note:

If an application supports independently fetchable fragments, it is possible to use the <esi:inline> for fetchable fragments by setting the fetchable attribute to yes. See Section 11.4.5 for further information about the fetchable attribute.

To use the <esi:inline> tag, the logical fragments in portal.esi are marked with the <esi:inline> tags. The personalized greeting, Weather Forecast, My Stocks, Promotion campaign, Latest News, and Latest Sports News naturally become fragments because they have individual caching properties and can be shared. The My Stock fragment is further broken down into five sub-fragments, one for each stock quote. In addition, to achieve the maximum fragment sharing, the common HTML code sections between each two personalized fragments are also enclosed as ESI fragments and are given constant names, so that the varying template contains as little common data as possible.

Example 11-6 shows portal.esi with <esi:inline> tags.

Example 11-6 portal.esi with inline Tags

<esi:inline name="/Common_Fragment_1" >
<!-- First common fragment -->
<HTML>
...
<!-- Personalized Greeting With ESI variable -->
  Welcome, $(QUERY_STRING{username})!
</esi:inline>

<esi:inline name="/Weathers_San_Francisco" >
...
<!-- Personalized Weather Forecast -->
Weather Forecast for San Francisco
<TABLE>
  <TR>
    <TD> 
      Currently: 50F
    </TD>
  </TR>
</TABLE>
</esi:inline>

<esi:inline name="/Common_Fragment_2" >
<!-- Second common fragment -->
...
</esi:inline>

<esi:inline name="/Stocks_$(QUERY_STRING{username})" >
<!-- Personalized Stock Quote Selections -->
<TABLE>
  <TR>
    <TD>
    <esi:inline name="/ticker_IBM">
      IBM 84.99
    </esi:inline>
    <BR>
    <esi:inline name="/ticker_ORCL">
      ORCL 13.379
    </esi:inline>
    <BR>
    <esi:inline name="/ticker_YHOO">
      YHOO 27.15
    </esi:inline>
    <TD>
  </TR>
</TABLE>
</esi:inline>

<esi:inline name="/Common_Fragment_3">
<!-- Third common fragment -->
...
</esi:inline>

<esi:inline name="/ExternalAdvertisement">
<!-- External Advertisement -->
<TABLE>
  <TR> 
    <TD>
    <a href="http://www.companyad.com/advert?promotionID=126532">
    <img src="http://www.companyad.com/advert_img?promotionID=126532">
    </a>
    </TD>
  </TR>
</TABLE>
</esi:inline>

<esi:inline name="/Common_Fragment_4">
<!-- Fourth common fragment -->
...
</esi:inline>

<esi:inline name="/Top_News_Finance">
<!-- Personalized Top News -->
Latest News for finance
<TABLE>
  <TR>
     Tech Spending Growth Indexes Little Changes
     Home Sales Hit Record High
     Gas Prices Dip Again
  </TR>
</TABLE>
</esi:inline>

<esi:inline name="/Sports_News_Soccer" >
<!-- Personalized Sports News -->
Latest Sports News for Soccer

<TABLE>
  <TR>
  Preparation for World Cup
  Youth Cup game on a Sunday
  Latest Scores
  </TR>
</TABLE>
</esi:inline>

<esi:inline name="/Common_Fragment_5" >
...
</esi:inline>

Example 11-7 shows the markup for the personalized greeting. The fragment is common to all personalized pages belonging to different users. Because the <esi:inline> tag assigns this fragment a constant name, a different user, such as John, would have the same fragment in his template with the same fragment name. Two fragments are shared if and only if their names are identical. This way, the same shared fragment in all templates only need a single update when it expires or is invalidated. $(QUERY_STRING{username}) is an ESI environment variable that provide access to value of the username. This variable is used here because this application uses the username query string parameter to pass along the user's name. By using this variable, the first fragment becomes common to all users.

Example 11-7 portal.esi Example with inline Tags: Personalized Greeting

<esi:inline name="/Common_Fragment_1" >
<!-- First common fragment -->
<HTML>
...
<!-- Personalized Greeting With ESI variable -->
  Welcome, $(QUERY_STRING{username})!
</esi:inline>

Example 11-8 shows the markup for Weather Forecast. The fragment is unique to each city. Every template selecting the same city would share this fragment with Mark's page due to the fragment naming.

Example 11-8 portal.esi Example with inline Tags: Weather Forecast

<esi:inline name="/Weathers_San_Francisco" >
<!-- Personalized Weather Forecast -->
Weather Forecast for San Francisco
<TABLE>
  <TR>
    <TD> 
      Currently: 50F
    </TD>
  </TR>
</TABLE>
</esi:inline>

Example 11-9 shows the markup for My Stocks. The stock quotes fragment encloses all stock picks in Mark's page. It is further divided into five sub-fragments, one for each stock pick, using nested <esi:inline> tags. Thus, Mark's ESI template references his stock selection fragment, which in turn references five particular stock pick fragments. While the stock picks are shared by many user's stock selection fragment, the stock selection fragment itself is also a template uniquely owned by Mark. This markup separates the unique information from the shared information, maximizing the reduction of cache updates and space consumption of personal stock selection.

Example 11-9 portal.esi Example: My Stocks Fragment

<esi:inline name="/Stocks_$(QUERY_STRING{username})" >
<!-- Personalized Stock Quote Selections -->
<TABLE>
  <TR>
    <TD>
    <esi:inline name="/ticker_IBM">
      IBM 84.99
    </esi:inline>
    <BR>
    <esi:inline name="/ticker_ORCL">
      ORCL 13.379
    </esi:inline>
    <BR>
    <esi:inline name="/ticker_YHOO">
      YHOO 27.15
    </esi:inline>
    <TD>
  </TR>
</TABLE>
</esi:inline>

Example 11-10 shows the markup for referencing an advertisement in the Promotion section. promotionID is the based on the user's identification.

Example 11-10 portal.esi Example with inline Tags: Promotion

<esi:inline name="/ExternalAdvertisement">
<!-- External Advertisement -->
<TABLE>
  <TR> 
    <TD>
    <a href="http://www.companyad.com/advert?promotionID=126532">
    <img src="http://www.companyad.com/advert_img?promotionID=126532">
    </a>
    </TD>
  </TR>
</TABLE>
</esi:inline>

Rotating advertisements that change in every response is an example of real- time content that renders little value in non-fetchable ESI <esi:inline> caching. Even the smallest portion of real-time content embedded as a non-fetchable ESI inline fragment would require the entire response to be regenerated and fetched, effectively creating cache misses all the time. To use ESI and dynamic content caching for these real-time fragments, use the <esi:include> tag.

See Section 11.2.3.1.2 for an example of using <esi:include> tag for real-time advertisements

The Latest News and Latest Sports News fragments are similar to the weather fragment. All the common areas are also defined as fragments. Although it is possible to leave them as part of the template, that would consume unnecessary storage space. Example 11-11 shows the markup.

Example 11-11 portal.esi Example with inline Tags: Latest News and Latest Sports News

<esi:inline name="/Top_News_Finance">
<!-- Personalized Top News -->
Latest News for finance
<TABLE>
  <TR>
     Tech Spending Growth Indexes Little Changes
     Home Sales Hit Record High
     Gas Prices Dip Again
  </TR>
</TABLE>
</esi:inline>


<esi:inline name="/Sports_News_Soccer" >
<!-- Personalized Sports News -->
Latest Sports News for Soccer
<TABLE>
  <TR>
  Preparation for World Cup
  Youth Cup game on a Sunday
  Latest Scores
  </TR>
</TABLE>
</esi:inline>
11.2.3.1.2 Portal Example Using Include Tags

This section shows how the <esi:include> tag can be used for fragmentation and assembly of fetchable fragments whose content are not embedded in the template.

Example 11-12 shows portal.esi with <esi:include> tags.

Example 11-12 portal.esi with include Tags

<HTML>
...
<!-- Personal Profile -->
<esi:comment text="Profile refers to environment variables stored in
/servlet/GetProfile. GetProfile servlet enables access to a set of environment
variables with personal profile information."/>
<esi:environment src="/servlet/GetProfile?username=$(QUERY_STRING{username})"
name="Profile"/>
...

<!-- Personalized Greeting With ESI variable -->
<esi:vars>Welcome, $(QUERY_STRING{username})!</esi:vars>
...


<!-- Personalized Weather Forecast -->
<TABLE>
  <TR> 
    <TD> 
      <esi:include src="/servlet/Weather?city=$(Profile{city})&state=$(Profile{state})"/>
    </TD>
  </TR>
</TABLE>
...

<!-- Personalized Stock Quote Selections -->
<TABLE>
  <TR> 
    <TD>
      <esi:include src="/servlet/PersonalizedStockSelection?username=$(QUERY_STRING{username})"/>
    </TD>
  </TR>
</TABLE>
...

<!-- External Advertisement -->
<TABLE>
  <TR> 
    <TD>
      <esi:try>
        <esi:attempt>
          <esi:comment text="Include an ad"/> 
          <esi:include src="/servlet/Advert"/>
        </esi:attempt>
        <esi:except> 
         <esi:comment text="Just write an HTML link instead"/>
         <A HREF="http://www.oracle.com">http://www.oracle.com</a> 
        </esi:except>
      </esi:try>
    </TD>
  </TR>
</TABLE>
...

<!-- Personalized Top News -->
Latest News for <esi:vars>$(Profile{news})</esi:vars>
<TABLE>
  <TR> 
    <TD>
      <esi:choose>
        <esi:when test="$(Profile{news}) == 'Internet'">
          <esi:include src="/servlet/News?type=Top&topic=internet"/> 
        </esi:when>
        <esi:when test="$(Profile{news}) == 'finance'">
         <esi:include src="/servlet/News?type=Top&topic=business"/> 
        </esi:when>
      <esi:otherwise>
      <esi:include src="/servlet/News?type=Top&topic=technology"/> 
      </esi:otherwise>
      </esi:choose>
    </TD>
  </TR>
</TABLE>
...


<!-- Personalized Sports News -->
Latest Sports News for <esi:vars>$(Profile{sport})</esi:vars>
<TABLE>
  <TR> 
    <TD>
      <esi:choose>
        <esi:when test="$(Profile{sport}) == 'golf'">
          <esi:include src="/servlet/News?type=Sports&topic=golf"/> 
        </esi:when>
        <esi:when test="$(Profile{sport}) == 'soccer'">
          <esi:include src="/servlet/News?type=Sports&topic=soccer"/> 
        </esi:when>
        <esi:when test="$(Profile{sport}) == 'basketball'">
          <esi:include src="/servlet/News?type=Sports&topic=basketball"/> 
        </esi:when>
        <esi:when test="$(Profile{sport}) == 'baseball'">
          <esi:include src="/servlet/News?type=Sports&topic=baseball"/> 
        </esi:when>
        <esi:otherwise>
          <esi:include src="/servlet/News?type=Sports&topic=soccer"/> 
        </esi:otherwise>
      </esi:choose>
    </TD>
  </TR>
</TABLE>

Example 11-13 specifies Profile to refer to the environment variables stored in GetProfile. GetProfile enables access to user profile variables, which are used as parameters in the included fragments:

Example 11-13 portal.esi Example: Custom Profile Environment Variable Setting

<!-- Personal Profile -->
<esi:comment text="Profile refers to environment variables stored in
/servlet/GetProfile. GetProfile servlet enables access to a set of environment
variables with personal profile information."/>

<esi:environment src="/servlet/GetProfile?username=$(QUERY_STRING{username})"
name="Profile"/>

Example 11-14 shows GetProfile, which provides access to the city, state, news, and sports environment variables.

Example 11-14 portal.esi Example: GetProfile File with Environment Variables

<?xml version="1.0"?>
<esi-environment esiversion="ORAESI/9.0.4">
  <city>San_Francisco</city>
  <state>CA</state>
  <news>finance</news>
  <sports>soccer</sports>
</esi-environment>

Example 11-15 shows the markup for the personalized greeting Welcome, Mark!. The personalized greeting is achieved by the <esi:vars> tag, which bases the greeting on the username parameter embedded in the URL. The parameter username is the registered user's name. This markup enables the personalized greeting to be included in the cacheable template page.

Example 11-15 portal.esi Example with vars tag: Personalized Greeting

<esi:vars>Welcome, $(QUERY_STRING{username})!</esi:vars>

Example 11-16 shows the markup for Weather Forecast. Weather Forecast includes a servlet fragment name Weather, which uses the value of the user's city and state environment variables in GetProfile to display the correct weather forecast for the user. Because GetProfile has a value of San Francisco for the city environment variable and California for the state environment variable, the weather forecast is for San Francisco, California.

Example 11-16 portal.esi Example with include Tags: Weather Forecast

<TABLE>
  <TR> 
    <TD> 
      <esi:include src="/servlet/Weather?city=$(Profile{city})&state=$(Profile{state})"/>
    </TD>
  </TR>
</TABLE>

The markup for My Stocks is depicted in Example 11-17. My Stocks includes a servlet fragment named PersonalizedStockSelection. The displayed stocks are based on the userID parameter encoded in the URL. userID is the registered user's unique ID.

Example 11-17 portal.esi Example with include Tags: My Stocks Fragment

<TABLE>
  <TR> 
    <TD>
      <esi:include src="/servlet/PersonalizedStockSelection?username=$(QUERY_STRING{username})"/>
    </TD>
  </TR>
</TABLE>

The markup for the included fragment PersonalizedStockSelection is depicted in Example 11-18. It includes fragments for three stock quotes: IBM, ORCL, and YHOO.

Example 11-18 portal.esi Example: PersonalizedStockSelection Fragment for Mark

<TABLE>
  <TR> 
    <TD>
    <BR>
    <esi:include src="Quote?symbol=IBM"/>
    <BR>
    <esi:include src="Quote?symbol=ORCL"/>
    <BR>
    <esi:include src="Quote?symbol=YHOO"/>
    <BR>
    </TD>
  </TR>
</TABLE>

Because the output is different for each user, the PersonalizedStockSelection fragment is not cacheable. However, the response to each of the included quotes is cacheable, enabling stock quotes to be shared by multiple users. Even when many users share quotes, only one browser reload is needed when the quotes are updated. For example, the PersonalizedStockSelection fragment for another user named Scott is depicted in Example 11-19. It includes fragments for three stock quotes: IBM, ORCL, and SCO. As described, IBM and ORCL are also shared by Mark. If Mark reloads the page first and caches the quotes, then the IBM and ORCL quotes for Scott are automatically refreshed.

Example 11-19 portal.esi Example: PersonalizedStockSelection Fragment for Scott

<TABLE>
  <TR> 
    <TD>
    <BR>
    <esi:include src="Quote?symbol=IBM"/>
    <BR>
    <esi:include src="Quote?symbol=ORCL"/>
    <BR>
    <esi:include src="Quote?symbol=SCO"/>
    <BR>
    </TD>
  </TR>
</TABLE>

Example 11-20 shows the markup for rotating advertisements in the Promotion section. The advertisements rotates in the sense that the advertisement changes for each response. By separating the generation of the included image fragment response from the template page, Oracle Web Cache can cache the template and integrate the dynamic advertisement into the template.

Example 11-20 portal.esi Example with include Tags: Promotion

<TABLE>
  <TR> 
    <TD>
      <esi:try>
        <esi:attempt>
          <esi:comment text="Include an ad"/> 
          <esi:include src="/servlet/Advert"/>
       </esi:attempt>
       <esi:except> 
         <esi:comment text="Just write an HTML link instead"/>
          <A HREF="www.oracle.com">www.oracle.com</a> 
       </esi:except>
      </esi:try>
    </TD>
  </TR>
</TABLE>

As shown in Example 11-21, the response to the included image fragment for the banner is not cacheable. When a user requests this page, Oracle Web Cache sends the request to the application Web server to generate the banner. From the application Web server, Advert generates the banner for the request.

Example 11-21 portal.esi Example: Rotating Banner Output

<TABLE>
  <TR> 
    <TD>
      <A HREF="http://www.companyad.com/redirect?refID=11934502">
      <IMG src="http://www.companyad.com/advert_img?refID=11934502"></A>
    </TD>
  </TR>
</TABLE>

As shown in Example 11-22, the next time the user reloads the page, Advert generates another banner for the request.

Example 11-22 portal.esi Example: Rotating Banner Reload

<TABLE>
  <TR> 
    <TD>
      <A HREF="http://www.companyad.com/redirect?refID=123456602">
      <IMG src="http://www.companyad.com/advert_img?refID=123456602"></A>
    </TD>
  </TR>
</TABLE>

The banner relies on alternate processing with the <esi:try> tag. If the servlet cannot run Advert, a link to www.oracle.com appears in the banner's place.

Example 11-23 shows the markup for Latest News and Latest Sports News:

  • Latest News displays the news headlines based on the user's news category, internet, finance, or technology, by using conditional processing with the <esi:choose> tag. Because GetProfile has a value of finance for the news environment variable, the headlines displayed relate to finance, /servlet/News?type=Top&topic=business.

  • Similarly, Latest Sports News displays the sports headlines based on the user's sports category, golf, soccer, basketball, baseball, or soccer, by using conditional processing. Because GetProfile has a value of soccer for the sports environment variable, the output includes headlines relating to soccer, /servlet/News?type=Sports&topic=soccer.

Example 11-23 portal.esi Example with include Tags: Latest News and Sports Sections

Latest News for <esi:vars>$(Profile{news})</esi:vars>
<TABLE>
  <TR> 
    <TD>
      <esi:choose>
        <esi:when test="$(Profile{news}) == 'internet'">
          <esi:include src="/servlet/News?type=Top&topic=internet"/> 
        </esi:when>
        <esi:when test="$(Profile{news}) == 'finance'">
         <esi:include src="/servlet/News?type=Top&topic=business"/> 
        </esi:when>
      <esi:otherwise>
      <esi:include src="/servlet/News?type=Top&topic=technology"/> 
      </esi:otherwise>
      </esi:choose>
    </TD>
  </TR>
</TABLE>
...
<!-- Personalized Sports News -->
Latest Sports News for <esi:vars>$(Profile{sport})</esi:vars>

<TABLE>
  <TR> 
    <TD>
      <esi:choose>
        <esi:when test="$(Profile{sport}) == 'golf'">
          <esi:include src="/servlet/News?type=Sports&topic=golf"/> 
        </esi:when>
        <esi:when test="$(Profile{sport}) == 'soccer'">
          <esi:include src="/servlet/News?type=Sports&topic=soccer"/> 
        </esi:when>
        <esi:when test="$(Profile{sport}) == 'basketball'">
          <esi:include src="/servlet/News?type=Sports&topic=basketball"/> 
        </esi:when>
        <esi:when test="$(Profile{sport}) == 'baseball'">
          <esi:include src="/servlet/News?type=Sports&topic=baseball"/> 
        </esi:when>
        <esi:otherwise>
          <esi:include src="/servlet/News?type=Sports&topic=soccer"/> 
        </esi:otherwise>
      </esi:choose>
    </TD>
  </TR>
</TABLE>

11.2.3.2 Example of Simple Personalization with Variable Expressions

ESI variables can be used within an HTML tag. For example, consider Example 11-24. Its HTML code uses PL/SQL for an HTML form with a text box in it.

Example 11-24 PL/SQL Code without Personalization

htp.p('<form action="test" method="GET">');
htp.p('<table border="0" >
      <tr>
      <td><input type="text" name="p_name" size="8" value="'||p_name||'"></td>
      </tr>
      <tr>
      <td><input type="submit" value="Search"></td>
      </tr>
</table>');

Example 11-25 shows how the $HTTP_COOKIE variable is used with the <esi:vars> tag to replace the value of p_name with the user's name.

Example 11-25 PL/SQL Code with Personalization through ESI

htp.p('<form action="test" method="GET">'); 
htp.p('<table border="0" > 
    <tr><esi:vars> 
         <td><input type="text" name="p_name" size="8" 
                          value="$(HTTP_COOKIE{'p_name'}"></td> 
         </tr></esi:vars> 
         <tr> 
         <td><input type="submit" value="Search"></td> 
         </tr> 
  </table>'); 

11.3 Using Inline Invalidation in HTTP Responses

Inline invalidation is implemented as part of Edge Side Includes (ESI) and provides a useful way for origin servers to "piggyback" invalidation messages on transactional responses sent to Web Cache. For instance, when a customer purchases a vegetarian cookbook on an e-commerce site, the confirmation response could contain instructions for invalidating all catalog pages related to the book, its author and vegetables. The ability to send invalidation message inline reduces the connection overhead associated with sending out-of-band invalidations and is a useful tool for ESI developers.

To configure inline invalidation:

  1. In the template page, configure the HTTP response with the Surrogate-Control response-header field that includes content="ESI-INV/1.0":

    Surrogate-Control: content="ESI-INV/1.0"
    
  2. In the body of the same response, use the <esi:invalidate> tag to insert either a basic or advanced inline invalidation request.

    You can insert an inline invalidation request anywhere in the ESI template. You can insert multiple requests, but only the first one processes. The execution of the inline invalidation is blocking. That is, if the ESI template contains other ESI features, inline invalidation is executed first.

    Basic invalidation syntax:

    <esi:invalidate [output="yes"]>
     <?xml version="1.0"?>
     <!DOCTYPE INVALIDATION SYSTEM "internal:///WCSinvalidation.dtd">
      <INVALIDATION VERSION="WCS-1.1">
        <SYSTEM>
         <SYSTEMINFO NAME="name" VALUE="value"/>
        </SYSTEM>  
        <OBJECT>
          <BASICSELECTOR URI="URL"/>
          <ACTION REMOVALTTL="TTL"/>
          <INFO VALUE="value"/>
        </OBJECT>
     </INVALIDATION>
    </esi:invalidate>
    

    Advanced invalidation syntax:

    <esi:invalidate [output="yes"]>
     <?xml version="1.0"?>
     <!DOCTYPE INVALIDATION SYSTEM "internal:///WCSinvalidation.dtd">
     <INVALIDATION VERSION="WCS-1.1">
        <SYSTEM>
         <SYSTEMINFO NAME="name" VALUE="value"/>
        </SYSTEM>  
           <OBJECT>
             <ADVANCEDSELECTOR URIPREFIX="prefix"
                               URIEXP="URL_expression"
                               HOST="host_name:port"
                               METHOD="HTTP_request_method"
                              BODYEXP="HTTP_body"/>
              <COOKIE NAME="cookie_name" VALUE="value"/>
              <HEADER NAME="HTTP_request_header" VALUE="value"/>
              <OTHER name="URI"
                     TYPE="SUBSTRING|REGEX"
                     VALUE="value"/>
             </ADVANCEDSELECTOR>
           </OBJECT>
     </INVALIDATION>
    </esi:invalidate>
    

For more information, see:

11.3.1 Example: Using Inline Invalidation

Following is an example about an online bike shop using inline invalidation in their simple Web application. It has two CGI scripts written in Perl. show_bike.pl displays how many bikes of a certain model are in stock. Since it involves database query and its result remains the same until a purchase occurs, show_bike.pl is cached. buy_bike.pl is used by customers to buy a bike. When this page is requested, show_bike.pl is no longer valid—an invalidation is needed.

Example 11-26 shows the code for show_bike.pl.

Example 11-26 show_bike.pl Code

#!/usr/local/bin/perl

# first, retrieve how many bikes are in stock 
# and assign it to $nBikes (omitted!)

print <<END;
Content-Type: text/html
Cache-Control: private
Surrogate-Control: max-age=3600

<html>
<body>
<h1>Bike: model 2005</h1>

<p>There are $nBikes bike(s) in stock for purchase!</p>
<p>Click <a href="/cgi/buy_bike.pl">here</a> to purchase a bike.</p>

</body>
</html>
END

Note that max-age=3600 informs Oracle Web Cache to only cache this page for up to an hour.

Example 11-27 shows the code for buy_bike.pl with an inline invalidation request.

Example 11-27 buy_bike.pl Code with an Inline Invalidation Request

#!/usr/local/bin/perl

print <<END;
Content-Type: text/html
Cache-Control: private
Surrogate-Control: content="ESI/1.0 ESI-INV/1.0"

<html>
<body>
<h1>Thank you for purchasing bike model 2000.</h1>

<p>Click <a href="/cgi/show_bike.pl">here</a> to read more 
about this model.</p>

<esi:invalidate>
 <?xml version="1.0"?>
 <!DOCTYPE INVALIDATION SYSTEM "internal:///WCSinvalidation.dtd">
  <INVALIDATION VERSION="WCS-1.1">
    <OBJECT>
      <BASICSELECTOR URI="/cgi/show_bike.pl"/>
      <ACTION REMOVALTTL="0"/>
    </OBJECT>
 </INVALIDATION>
</esi:invalidate>

<p>Thanks again!</p>
</body>
</html>
END

The ESI-INV/1.0 token in Surrogate-Control instructs Oracle Web Cache to process the <esi:invalidate> tag.

Example 11-28 shows the browser response for buy_bike.pl. Because Oracle Web Cache has already processed the inline invalidation request, the inline invalidation is not present in the response.

Example 11-28 Browser Response of buy_bike.pl

Content-Type: text/html
Cache-Control: private
Surrogate-Control: content="ESI/1.0 ESI-INV/1.0"

<html>
<body>
<h1>Thank you for purchasing bike model 2000.</h1>

<p>Click <a href="/cgi/show_bike.pl">here</a> to read more 
about this model.</p>

<p>Thanks again!</p>
</body>
</html>

Debugging Tips

To facilitate debugging, the application developer can perform the following:

  • Add the Surrogate-Capability request header that includes "ESI-INV/1.0":

    Surrogate-Capability: content="ESI-INV/1.0"
    

    When the Surrogate-Capability request header is added for inline invalidation, Oracle Web Cache includes the invalidation request in the response.

  • Enable the output attribute of the <esi:invalidate> tag.

    When the output attribute is enabled, Oracle Web Cache includes the invalidation result in the response enclosed within comments <!--result-->.

Example 11-29 shows the browser response of buy_bike.pl when both the Surrogate-Capability request header is enabled for the inline invalidation and the output attribute of the <esi:invalidate> tag is enabled.

Example 11-29 Browser Response of show_bike.pl with Diagnostic Inline Invalidation Information

Content-Type: text/html
Cache-Control: private
Surrogate-Control: content="ESI/1.0 ESI-INV/1.0"

<html>
<body>
<h1>Thank you for purchasing bike model 2000.</h1>

<p>Click <a href="/cgi/show_bike.pl">here</a> to read more 
about this model.</p>

<esi:invalidate output="yes">
 <?xml version="1.0"?>
 <!DOCTYPE INVALIDATION SYSTEM "internal:///WCSinvalidation.dtd">
  <INVALIDATION VERSION="WCS-1.1">
    <OBJECT>
      <BASICSELECTOR URI="/cgi/show_bike.pl"/>
      <ACTION REMOVALTTL="0"/>
    </OBJECT>
 </INVALIDATION>
</esi:invalidate>

<!--
<?xml version="1.0"?> 
<!DOCTYPE INVALIDATIONRESULT SYSTEM "internal:///WCSinvalidation.dtd">
<INVALIDATIONRESULT VERSION="WCS-1.1">
   <OBJECTRESULT>
     <BASICSELECTOR URI="/cgi/show_bike.pl/>
     <RESULT ID="1" STATUS="SUCCESS" NUMINV="1"/>
     </OBJECTRESULT>
</INVALIDATIONRESULT>
-->

<p>Thanks again!</p>
</body>
</html>

11.4 ESI Tag Descriptions

This section describes the following ESI tags, which are used for partial page caching operations:

11.4.1 ESI choose | when | otherwise Tags

The <esi:choose>, <esi:when>, and <esi:otherwise> conditional tags provide the ability to perform logic based on Boolean expressions.

11.4.1.1 Syntax

<esi:choose>
  <esi:when test="BOOLEAN_expression">
    Perform this action
  </esi:when>
  <esi:when test="BOOLEAN_expression">
    Perform this action
  </esi:when>
  <esi:otherwise>
    Perform this other action
  </esi:otherwise>
</esi:choose>

11.4.1.2 Attributes

test—Specifies the Boolean operation

11.4.1.3 Usage

  • Each <esi:choose> tag must have a least one <esi:when> tag, and may optionally contain exactly one <esi:otherwise> tag.

  • Oracle Web Cache executes the first <esi:when> tag whose test attribute evaluates truthfully, and then exit the <esi:choose> tag. If no <esi:when> tag evaluates to true and an <esi:otherwise> tag is present, that element's content executes.

  • Other HTML or ESI element can be included inside <esi:when> or <esi:otherwise> elements.

11.4.1.4 Boolean Expressions

The test attribute uses Boolean expressions to determine how to evaluate true or false logic. ESI supports the following Boolean operators:

  • == (equal to)

  • != (not equal to)

  • > (greater than)

  • < (less than)

  • >= (greater than or equal to)

  • <= (less than or equal to)

  • & (and)

  • | (or)

  • ! (not)

Note the following about the use of Boolean expressions:

  • Operands associate from left to right.

    Sub-expressions can be grouped with parentheses to explicitly specify association.

  • If both operands are numeric, then the expression is evaluated numerically.

  • If either operand is non-numeric, then both operands are evaluated as strings. For example, 'a'==3 evaluates to 'a'=='3', where 3 is evaluated as a string.

  • The comparison of two Boolean expressions results in an undefined operation.

  • If an operand is empty or undefined, then the expression always evaluates to false.

  • The logical operators (&, !, and|) are used to qualify expressions, but cannot be used to make comparisons.

  • Use single quotes (') for constant strings. For example, the following string is a valid construction:

    $(HTTP_COOKIE{name})=='typical'
    
  • Escaped single quotes (\') are not permitted. For example, the following is not supported:

    $(HTTP_COOKIE{'user\'s name'})=='typical'
    
  • Arithmetic operations and assignments are not permitted.

  • A null value evaluates whether a variable is empty.

    When a number is compared with null, that number is converted into an equivalent string and compared against an empty string. In the following ESI markup, $(logindata{name}) is a variable that provides access to the value of the name. If name is empty and evaluates to null, then the expression evaluates to true; if name is not empty and does not evaluate to null, then the expression evaluates to false.

    Note:

    If a variable exists but evaluates to an empty string, then the value is not considered null.
    <esi:choose>
      <esi:when test="$(logindata{name}) == null">
        <esi:include src=/login/$(logindata{name})"/>
     </esi:when>
     <esi:otherwise>
       <esi:include src=/login/guest.html"/>
     <esi:otherwise>
    </esi:choose>  
    

The following expressions show correct usage of Boolean operators:

!(1==1)
!('a'<='c')
(1==1)|('abc'=='def')
(4!=5)&(4==5)

The following expressions show incorrect usage of Boolean operators:

(1 & 4)
("abc" | "edf")

11.4.1.5 Statements

Statements must be placed inside a <esi:when> or <esi:otherwise> subtag. Statements outside the subtags cannot be evaluated as conditions. Example 11-30 shows invalid placement of statements.

Example 11-30 Statement Placement

<esi:choose>
  This markup is invalid because any characters other than whitespace 
  are not allowed in this area.
  <esi:when test="$(HTTP_HOST) == 'www.company.com'">
    <esi:include src="/company.html" />
  </esi:when>
     This markup is invalid because any characters other than whitespace 
     are not allowed in this area.
  <esi:when test="$(HTTP_COOKIE{fragment) == 'First Fragment'">
    <img src="/img/TheImage.gif">
  </esi:when>
     This markup is invalid because any characters other than whitespace 
     are not allowed in this area.
   <esi:otherwise>
     The default selection.
  </esi:otherwise>
   This markup is invalid because any characters other than whitespace 
   are not allowed in this area.
</esi:choose>

11.4.1.6 Example

The following ESI markup includes advanced.html for requests that use the cookie Advanced and basic.html for requests that use the cookie Basic:

<esi:choose>
  <esi:when test="$(HTTP_COOKIE{group})=='Advanced'">
    <esi:include src="http://www.company.com/advanced.html"/>
  </esi:when>
  <esi:when test="$(HTTP_COOKIE{group})=='Basic User'">
    <esi:include src="http://www.company.com/basic.html"/>
  </esi:when>
  <esi:otherwise>
    <esi:include src="http://www.company.com/new_user.html"/>
  </esi:otherwise>
</esi:choose>

11.4.2 ESI comment Tag

The <esi:comment> tag enables you to comment ESI instructions, without making the comments available in the output.

11.4.2.1 Syntax

<esi:comment text="text commentary"/>

<esi:comment> is an empty element, and does not have an end tag.

11.4.2.2 Usage

The <esi:comment> tag is not evaluated by Oracle Web Cache. If comments must be visible in the HTML output, use standard XML/HTML comment tags.

11.4.2.3 Example

The following ESI markup provides a comment for an included GIF file:

<esi:comment text="the following animation will have a 24 hour TTL"/>
<esi:include src="http://www.company.com/logo.gif" onerror="continue" />

11.4.3 ESI environment Tag

The <esi:environment> tag enables you to include custom environment variables from included fragments. When included, these variables can then be used with the other ESI tags.

11.4.3.1 Syntax

There are two forms of this tag. In the first form, <esi:environment> does not have a closing </esi:environment> tag:

<esi:environment src="environment_URL" name="environment_name"  [max-age="expiration_time [+ removal_time]]" [method="GET|POST"] [onerror="continue"] [timeout="fetch_time"]/>

In the second form with elements, <esi:environment> has a closing </esi:environment> tag:

<esi:environment src="environment_URL" name="environment_name"
   [max-age="expiration_time [+ removal_time]"] [method="GET|POST"]
   [onerror="continue"] [timeout="fetch_time"]>
  [<esi:request_header name="request_header" value="value"/>]
  [<esi:request_body value="value"/>]
  [<esi:log>log_message</esi:log>]
</esi:environment>

11.4.3.2 Attributes

  • src—Specifies the URL from which to obtain environment variables and their values.

    The URL can be either an absolute or relative URL. When specifying an absolute URL, use the following formats:

    • "http://host_name:port/path/filename"

    • "https://host_name:port/path/filename"

    If you specify the host name for an absolute URL, you must prefix it with http:// or https://. An HTML parser treats the host:80 in the following URL as a folder name rather than a host name:

    src="host:80/index.htm"
    

    To make this URL valid, you specify the following:

    src="http://host:80/index.htm"
    

    Relative URLs are resolved relative to the template page. The result sets the ESI environment for the current template.

    The source code of the URL requires the following XML format:

    <?xml version="1.0"?>
    <esi:environment esiversion="ORAESI/9.0.4">
      <variable_name>variable_value</variable_name>
      <variable_name>variable_value</variable_name>
    </esi:environment>
    
  • name—Specifies the name to use to refer to the environment variable.

  • method—Specifies the HTTP request method of the environment fragment. Valid values are GET or POST.

  • max-age—Specifies the time, in seconds, to expire the XML file, and optionally, specifies the time, in seconds, to remove the XML file after the expiration time.

  • timeout—Specifies the time, in seconds, for the fragment to be fetched. If the fragment has not been fetched within the time interval, the fetch is aborted.

  • onerror—Specifies that if the fetch failed on the src object, to ignore the ESI tag and serve the page.

11.4.3.3 Elements

  • request_body—Specifies the HTTP request body of the fragment.

  • request_header—Specifies an HTTP request header field and value for Oracle Web Cache to use.

  • log—Specifies a log message of the fragment to be included in the access_log_file.fragment file when the x-esi-info log field is set. You can provide a descriptive text string that identifies the fragment and the application that generated the fragment. By providing descriptive text, you can easily identify the fragment in the log file, enabling you to determine how often the fragment is requested.

See Table 9-5 for further information about the x-esi-info log field.

11.4.3.4 Syntax Usage

  • Specify only one <esi:environment> tag for each template page, before other ESI tags.

  • The attributes do not have to be in a particular order.

  • Do not specify multiple request_body elements.

  • You can have zero or more request_header elements.

    Use multiple request_header elements to specify multiple HTTP request header fields:

    <esi:environment src="environment_URL" 
       [max-age="expiration_time [+ removal_time]"][method="GET|POST"]
       [onerror="continue"] [timeout="fetch_time"]>
      <esi:request_header name="request_header" value="value"/>
      <esi:request_header name="request_header" value="value"/>
    </esi:environment>
    
  • If no request_header elements are specified, Oracle Web Cache uses other request headers from the parent page.

  • Do not specify multiple log elements.

For more information, see:

11.4.3.5 Example

The following ESI output specifies logindata to refer to the environment variables stored in catalog.xml. The file catalog.xml enables access to the value of the vendorID environment variable, which is used as a parameter in the included URL:

<esi:environment src="/catalog.xml" name="logindata"/>
<esi:include src="http://provider.com/intranetprovider?vendorID=$(logindata{vendorID})"/>

The file catalog.xml has the following content:

<?xml version="1.0"?>
<esi:environment esiversion="ORAESI/9.0.4">
  <product_description>stereo</product_description>
  <vendorID>3278</vendorID>
  <partner1>E-Electronics</partner1>
  <partner2>E-City</partner2>
</esi:environment>

The following ESI output specifies logindata to refer to the environment variables stored in env.dat. The file env.dat enables access to the value of the env environment variable, which is used as a parameter in the included log message for dir1.txt. The log messages for dir1.txt and esi-log2.html are written to the access_log.fragment file when the x-esi-info log field is set and the fragments are requested.

<esi:environment src="/esi/env.dat" name="env">
  <esi:log>Used environment /esi/env.dat</esi:log>
</esi:environment>

<esi:include src="/cached/dir1.txt">
  <esi:log>Fragment:/cache/dir1.txt is included, by $(env{xl_name})</esi:log>
</esi:include>

<font color="red">Including /cgi-bin/esi-fetch.sh?/esi/esi-log2.html in esi-log1.html </font>
<esi:include src="/cgi-bin/esi-fetch.sh?/esi/esi-log2.html">
  <esi:log>Fragment: /cgi-bin/esi-fetch.sh?/esi/esi-log2.html is included
 </esi:log>

11.4.4 ESI include Tag

The <esi:include> tag provides syntax for including fragments.

See Section 11.1.8 for a comparison of <esi:inline> and <esi:include> usage.

11.4.4.1 Syntax

There are two forms of this tag. In the first form, <esi:include> does not have a closing </esi:include> tag:

<esi:include src="URL_fragment" [alt="URL_fragment"]
[max-age="expiration_time [+removal_time]]" [method="GET|POST"] [onerror="continue"] [redirect=yes|no] [timeout="fetch_time"]/>

In the second form, with elements, <esi:include> has a closing </esi:include> tag:

<esi:include src="URL_fragment" [alt="URL_fragment"]
   [max-age="expiration_time[+removal_time]"] [method="GET|POST"]
   [onerror="continue"] [redirect=yes|no] [timeout="fetch_time"]>
  [<esi:request_header name="request_header" value="value"/>]
  [<esi:request_body value="value"/>]
  [<esi:log>log_message</esi:log>]
</esi:include>

11.4.4.2 Attributes

  • src—Specifies the URL of the fragment to fetch. The URL can be a literal string or it can include variables.

    The URL can either be an absolute or relative URL. When specifying an absolute URL, use the following formats:

    • "http://host_name:port/path/filename"

    • "https://host_name:port/path/filename"

    If you specify the host name for an absolute URL, you must prefix it with http:// or https://. An HTML parser treats the host:80 in the following URL as a folder name rather than a host name:

    src="host:80/index.htm"
    

    To make this URL valid, you specify the following:

    src="http://host:80/index.htm"
    

    Relative URLs are resolved relative to the template page. The included result replaces the element in the markup served to the browser.

    You can specify an XML fragment if the XML file fragment is valid XML. For example, the following specifies that Oracle Web Cache use XSL Transformations (XSLT) to transform the XML into HTML using a style sheet. The style sheet maps XML formats to HTML formats:

    <?xml version="1.0"?>
    <?xml-stylesheet type="text/xml" href="stylesheet.xsl"?>
    

    Ensure that both the XML fragment and the XSL style sheet response pages are configured with a Content-Type response-header field that includes text and XML media types. For example:

    Content-Type: text/xml
    

    For more information about XSLT, see http://www.w3.org/TR/xslt.

  • alt—Specifies an alternative resource if the src is not found. The requirements for the value are the same as those for src.

  • max-age—Specifies the time, in seconds, to expire the fragment, and optionally, specifies the time, in seconds, to remove the fragment after expiration time. Use this attribute if the template page has a higher tolerance for stale fragments than specified by the time-to-live parameters in fragment responses.

  • method—Specifies the HTTP request method of the fragment. Valid values are GET or POST.

  • onerror—Specifies that if the fetch failed on the src object to ignore the ESI tag and serve the page.

  • redirect—Specifies how to serve the fragment when the src fragment resides temporarily under a different URL. yes specifies that the URL be redirected and displayed; no specifies that the fragment URL not be redirected and an HTTP 302 Found status code be served for the fragment. yes is the default.

  • timeout—Specifies the time, in seconds, for the fragment to be fetched. If the fragment has not been fetched within the time interval, the fetch is aborted.

    See Section 11.1.7 for usage notes on alt and onerror.

11.4.4.3 Elements

  • request_body—Specifies the HTTP request body of the fragment.

  • request_header—Specifies an HTTP request header field and value for Oracle Web Cache to use. You can specify multiple HTTP request headers. When this attribute is specified, all request headers from the parent fragment or template page are ignored.

  • log—Specifies a log message of the fragment to be included in the access_log.fragment file when the x-esi-info log field is set. You can provide a descriptive text string that identifies the fragment and the application that generated the fragment. By providing descriptive text, you can easily identify the fragment in the log file, enabling you to determine how often the fragment is requested.

    See Table 9-5 for further information about the x-esi-info log field.

11.4.4.4 Syntax Usage

  • <esi:include> supports up to three levels of nesting.

  • <esi:include> does not support escaped double quotes (\"). For example, the following is not supported:

    <esi:include src="file\"user.htm"/>
    
  • The attributes do not have to be in a particular order.

  • The src attribute supports both HTTP and HTTPS. Oracle Web Cache permits the template and fragments to use different protocols. Note the following:

    • If the src attribute specifies a fragment's relative path, such as src="/PersonalizedGreeting", the template's protocol is used.

    • If the protocol used in the src attribute does not match the protocol specified in the Site-to-Server Mapping page (Origin Servers, Sites, and Load Balancing > Site-to-Server Mapping) of Oracle Web Cache Manager, then Oracle Web Cache uses the protocol configured for the origin server in the Site-to-Server Mapping page. Oracle Web Cache also reports the following warning message to the event log:

      [Date] [warning 11250] [ecid: request_id, serial_number]
      ESI include fragment protocol does not match origin server protocol: 
      Origin Server Protocol=protocol URL=URL
      

      For example, if the template page is configured with <esi:include> src="https://www.company.com:80/gifs/frag1.gif"/> and the site-to-server mapping specifies HTTP for the origin server, then http://www.company.com:80/gifs/frag1.gif is used and the following message appears in the event log:

      [03/Feb/2005:23:16:46 +0000] [warning 11250] [ecid: 90125204378,0] 
      ESI include fragment protocol does not match origin server protocol:
      Origin Server Protocol=http URL=https://www.company.com:80/gifs/frag1.gif
      
  • Do not specify multiple request_body elements.

  • You can have zero or more request_header elements.

  • Use multiple request_header elements to specify multiple HTTP request header fields:

    <esi:include src="URL_fragment" 
      [max-age="expiration_time[+removal_time]"] [method="GET|POST"]
      [onerror="continue"] [timeout="fetch_time"]>
      <esi:request_header name="request_header" value="value"/>
      <esi:request_header name="request_header" value="value"/>
    </esi:include>
    
  • Do not specify multiple log elements.

11.4.4.5 Usage

The <esi:include> tag instructs Oracle Web Cache to fetch the fragment specified by the src attribute.

If the include is successful, the contents of the fetched src URL are displayed. The included object is included exactly at the point of the include tag. For example, if the include tag is in a table cell, the fetched object is displayed in the table cell.

The max-age control directive in the Surrogate-Control response-header field applies to the response; the max-age attribute applies only to that particular usage of the fragment response through the <esi:include> tag. If both the max-age control directive in the Surrogate-Control response-header field and the max-age attribute are set, then the effective expiration and removal time-to-live for this particular inclusion are the longest maximum age of the expiration and the removal time-to-live, respectively. If a particular page has a greater tolerance for staleness of a fragment, then set the max-age attribute to a longer time than the max-age control directive. Use the max-age attribute to increase cache hits by serving fragments stale until the removal time. max-age=infinity specifies that the object never expires.

If method is not set, then GET is assumed. However, if the request_body element is set, then POST is assumed.

Oracle Web Cache generates the following HTTP request headers for all fragment requests:

  • Host

  • Content-Length

  • Surrogate-Capability

  • Connection

The request_header element enables you to control HTTP headers other than these. Do not specify these HTTP request headers as request_header attributes, as a conflict can affect the operation of Oracle Web Cache.

If no request_header elements are specified, Oracle Web Cache uses other request headers from the parent page.

See Section 11.1.8 for a comparison of <esi:inline> and <esi:include> usage.

11.4.4.6 Examples

The following ESI markup includes a file named frag1.htm. The fragment must be fetched within 60 seconds. If the fetch fails, Oracle Web Cache ignores the includes and serves the page. If the fetch succeeds, Oracle Web Cache includes the fragment. Oracle Web Cache expires the fragment after five minutes, and removes it after another eight minutes.

<esi:include src="/frag1.htm" timeout="60" maxage="300+480" onerror="continue"/>

The following ESI output includes the result of a dynamic query:

<esi:include src="/search?query=$QUERY_STRING(query)"/>

The following ESI output includes a personalized greeting, a Cookie HTTP request header, and an HTTP request body that includes the date. Log message "Fragment: /Personalized Greeting is included" writes to the access_log.fragment file when the x-esi-info log field is set and the fragment is requested.

<esi:include src="/PersonalGreeting">
  <esi:request_header name="Cookie" value="pname=Scott Tiger"/>
  <esi:request_body value="day=05, month=10, year=2001"/>
  <esi:log>Fragment: /Personalized Greeting is included</esi:log>
</esi:include>

For more information, see Section 11.2.3.1 for an extended example of <esi:include> usage.

11.4.5 ESI inline Tag

The <esi:inline> tag marks a fragment as a separately cacheable fragment, embedded in the HTTP response of another object. Oracle Web Cache stores and assembles these fragments independently as <esi:include> fragments.

See Section 11.1.8 for a comparison of <esi:inline> and <esi:include> usage.

11.4.5.1 Syntax

<esi:inline name="URL" fetchable="yes|no" 
 [max-age="expiration_time [+ removal_time]"] [timeout="fetch_time"]
 Embedded HTML code
</esi:inline>

11.4.5.2 Attributes

  • name—Specifies a unique name for the fragment in URL format.

  • fetchableyes instructs Oracle Web Cache to fetch a fragment from the origin server when it expires. The template for the fragment is not included during this fetching process. no instructs Oracle Web Cache to fetch the entire template from the origin server when there is a cache miss, and then try to extract all the fragments from the template.

  • max-age—Specifies the time, in seconds, to expire the fragment, and optionally, specifies the time, in seconds, to remove the fragment after the expiration time. Use this attribute if the template page has a higher tolerance for stale fragments than specified by the time-to-live parameters in fragment responses.

  • timeout—Specifies the time, in seconds, for the fragment to be fetched. If the fragment has not been fetched within the time interval, the fetch is aborted.

11.4.5.3 Usage

Some inline fragments are only delivered as part of an HTTP response for another object. These are not independently fetchable by Oracle Web Cache the way <esi:include> fragments are. When a non-fetchable fragment is needed by Oracle Web Cache, it must request the object from which the inline fragment was extracted.

When a non-fetchable <esi:inline> fragment is not found in the cache, Oracle Web Cache re-fetches the fragment's parent template. This behavior implies that the parent cannot be another non-fetchable <esi:inline> fragment. If the parent is an <esi:inline> non-fetchable fragment, the response returned to the browser is undefined.

For more information, see:

11.4.5.4 Example

The following ESI output embeds financial headlines:

<esi:inline name="/Top_News_Finance">
Latest News for Finance
<TABLE>
  <TR>
    Blue-Chip Stocks Cut Losses; Nasdaq Up MO
    French rig factory with explosives New York Times
    Volkswagen faces Brazil strike CNN Europe
    Airbuss reliability record BBC
  </TR>
</TABLE>
</esi:inline>

See Section 11.2.3.1 for an extended example of <esi:inline> usage.

11.4.6 ESI invalidate Tag

The <esi:invalidate> tag enables you to configure an invalidation request within the response of a browser page.

11.4.6.1 Syntax

Basic invalidation syntax:

<esi:invalidate [output="yes"]>
 <?xml version="1.0"?>
 <!DOCTYPE INVALIDATION SYSTEM "internal:///WCSinvalidation.dtd">
  <INVALIDATION VERSION="WCS-1.1">
    <SYSTEM>
     <SYSTEMINFO NAME="name" VALUE="value"/>
    </SYSTEM>  
    <OBJECT>
      <BASICSELECTOR URI="URL"/>
      <ACTION REMOVALTTL="TTL"/>
      <INFO VALUE="value"/>
    </OBJECT>
 </INVALIDATION>
</esi:invalidate>

Advanced invalidation syntax:

<esi:invalidate [output="yes"]>
 <?xml version="1.0"?>
 <!DOCTYPE INVALIDATION SYSTEM "internal:///WCSinvalidation.dtd">
 <INVALIDATION VERSION="WCS-1.1">
    <SYSTEM>
     <SYSTEMINFO NAME="name" VALUE="value"/>
    </SYSTEM>  
       <OBJECT>
         <ADVANCEDSELECTOR URIPREFIX="prefix"
                           URIEXP="URL_expression"
                           HOST="host_name:port"
                           METHOD="HTTP_request_method"
                          BODYEXP="HTTP_body"/>
          <COOKIE NAME="cookie_name" VALUE="value"/>
          <HEADER NAME="HTTP_request_header" VALUE="value"/>
          <OTHER name="URI"
                 TYPE="SUBSTRING|REGEX"
                 VALUE="value"/>
         </ADVANCEDSELECTOR>
      <ACTION REMOVALTTL="TTL"/>
      <INFO VALUE="value"/>
      </OBJECT>
 </INVALIDATION>
</esi:invalidate>

11.4.6.2 Attributes

  • outputyes specifies that the invalidation result be included in the browser response, enclosed within comments <!--result-->. no specifies that the invalidation result not be displayed in the output. Specify a value of yes for a test environment; specify a value of no for a production environment.

11.4.6.3 Usage

See Section 11.3.

11.4.6.4 Example

See Section 11.3.1.

11.4.7 ESI remove Tag

The <esi:remove> tag allows for specification of non-ESI markup output if ESI processing is not enabled with the Surrogate-Control header or there is not an ESI-enabled cache.

11.4.7.1 Syntax

<esi:remove> HTML output...</esi:remove>

11.4.7.2 Usage

Any HTML or ESI elements can be included within this tag, except other <esi:remove> tags. Note that nested ESI tags are not processed.

11.4.7.3 Example

The following ESI markup includes http://www.company.com if the <esi:include> content cannot be included:

<esi:include src="http://www.company.com/ad.html"/>
<esi:remove>
  <A HREF="http://www.company.com">www.company.com</A>
</esi:remove>

Normally, when Oracle Web Cache processes this example block, it fetches the ad.html file and includes it into the template page while silently discarding the <esi:remove> tag and its contents. If ESI processing is not enabled, all of the elements are passed through to the browser, which ignores ESI markup. However, the browser displays the <A HREF=...> HTML link.

11.4.8 ESI try | attempt | except Tags

The <esi:try> tag provides for exception handling. The <esi:try> tag must contain exactly one instance of an <esi:attempt> tag and one or more <esi:except> tags. See Section 11.1.7 for usage notes on alt and onerror.

11.4.8.1 Syntax

In the following form, only one <esi:except> tag is supported:

<esi:try>
  <esi:attempt>
    Try this...
  </esi:attempt>
  <esi:except>
    If the attempt fails, then perform this action...
  </esi:except>
</esi:try>

In the following form, multiple <esi:except> tags with different types are supported:

<esi:try>
  <esi:attempt>
    Try this...
  </esi:attempt>
  <esi:except [type="type"]>
    If the attempt fails, then perform this action...
  </esi:except>
  <esi:except [type="type"]>
    Perform this action...
  </esi:except>
  <esi:except>
    If the attempt fails, then perform this action...
  </esi:except>
</esi:try>

11.4.8.2 Usage

Oracle Web Cache first processes the contents of <esi:attempt>. A failed <esi:attempt> triggers an error and causes Oracle Web Cache to process the contents of the <esi:except> tag.

Specify an <esi:except> tag without a type for general errors; specify an <esi:except> tag with a type for specific errors. The <esi:except> tag accepts the following case-insensitive types:

  • nestingtoodeep: An error occurs because the fragment include depth has exceeded the maximum include depth.

  • originserverbusy: An error occurs because the origin server for this fragment is busy and cannot accept new requests now. This is caused by Oracle Web Cache-to-origin server request queue limit being reached.

  • noconnection: An error occurs because the cache cannot connect to the origin server serving this fragment.

  • networktimeout: An error occurs because a fragment request to the origin server has timed out in the network connection.

  • httpclienterror: An error occurs because the origin server returns an HTTP 4xx status code, a client error, such as a malformed HTTP request or an unauthorized access.

  • httpservererror: An error occurs because the origin server returns an HTTP 5xx status code, a server error.

  • incompatiblefragmentversion: An error occurs because a fragment's processing requirement is not supported or not compatible with the template. <!-- WEBCACHETAG--> and <!-- WEBCACHEEND--> processing in an ESI fragment is not compatible with ESI processing. A fragment may be plain data that does not need any processing in the cache, or it may be an ESI template itself that requires processing of ESI features supported in this release. The ESI features in use are specified by the Surrogate-Control content control directive.

  • incorrectresponseheader: An error occurs because the response headers for a fragment causes the error.

  • incorrectesifragment: An error occurs when Oracle Web Cache tries to parse or process the ESI fragment response body due to errors in the body.

  • incorrectxmlfragment: An error occurs because there is an error in XSLT retrieval, parsing, or processing by Oracle Web Cache.

11.4.8.3 Example

The following ESI markup attempts to fetch an advertisement. If the advertisement cannot be included, Oracle Web Cache includes a static link instead.

<esi:try>
  <esi:attempt>
    <esi:comment text="Include an ad"/>
    <esi:include src="http://www.company.com/ad1.htm"/>
  </esi:attempt>
  <esi:except>
    <esi:comment text="Just write some HTML instead"/>
    <a href=www.company.com>www.company.com</a>
  </esi:except>
</esi:try>

The following ESI markup attempts to fetch a fragment. If the fragment cannot be included because of httpclienterror, then Oracle Web Cache includes /cgi-bin/esi-fetch?/esi/tryNestL1.html instead.

<esi:try>
  <esi:attempt>
    <esi:include src="/frag.html"/>
  </esi:attempt>
  <esi:except type="httpclienterror">
    <esi:include src="/cgi-bin/esi-fetch?/esi/tryNestL1.html"/>
  </esi:except>
</esi:try>

The following <esi:try> attempts to include the fragment http://server.portal.com/pls/ppcdemo/!PCDEMO.wwpro_app_provider.execute_portlet/513104940/26 containing several HTTP request headers. If the fragment cannot be included because of various type errors, Oracle Web Cache returns an Unknown ESI Exception error.

<esi:try>
  <esi:attempt>
    <esi:include src="http://server.portal.com/pls/ppcdemo/!PCDEMO.wwpro_app_provider.execute_portlet/513104940/26" timeout="15000" >
      <esi:request_header name="X-Oracle-Device.MaxDocSize" value="0"/>
      <esi:request_header name="Accept" 
      value="text/html,text/xml,text/vnd.oracle.mobilexml"/>
      <esi:request_header name="User-Agent" 
        value="Mozilla/4.0 (compatible; MSIE 5.5; Windows; YComp 5.0.0.0) 
        RPT-HTTPClient/0.3-3"/>
      <esi:request_header name="Device.Orientation" value="landscape"/>
      <esi:request_header name="Device.Class" value="pcbrowser"/>
      <esi:request_header name="PORTAL-SUBSCRIBER" value="us"/>
      <esi:request_header name="Device.Secure" value="false"/>
      <esi:request_header name="PORTAL-SUBSCRIBER-DN"
         value="dc=us,dc=oracle,dc=com"/>
      <esi:request_header name="PORTAL-SUBSCRIBER-GUID"
         value="A5EE385440E6252BE0340800208A8B00"/>
      <esi:request_header name="Accept-Language" value="en-us"/>
      <esi:request_header name="PORTAL-USER-DN"
         value="cn=public,cn=users,dc=us,dc=oracle,dc=com"/>
      <esi:request_header name="PORTAL-USER-GUID"
         value="A5EE55B396E22651E0340800208A8B00"/>
      <esi:request_header name="Content-Type"
         value="application/x-www-form-urlencoded"/>
    </esi:include>
  </esi:attempt>
  <esi:except type="incompatiblefragmentversion" >
     This happens when a fragment's processing requirement is not supported 
     or not compatible with the template.
  </esi:except>
  <esi:except type="noconnection" >
     The cache is unable to connect to the origin server serving this fragment.
  </esi:except>
  <esi:except type="nestingtoodeep" >
     The fragment include depth has exceeded the maximum include depth. The
     default value defined in Web Cache is 3.
  </esi:except>
  <esi:except type="httpservererror" >
     The origin server returns an HTTP 5xx status code, a server error.
  </esi:except>
  <esi:except type="httpclienterror" >
     The origin server returns an HTTP 4xx status code, a client error, such as
     a malformed HTTP request or an unauthorized access.
  </esi:except>
  <esi:except type="incorrectresponseheader" >
     This happens when the response headers for a fragment cause the error.
  </esi:except>
  <esi:except type="incorrectxmlfragment" >
     This happens when there is any kind of error in Oracle Web Cache XSLT
     retrieval, parsing, or processing.
  </esi:except>
  <esi:except type="originserverbusy" >
     The origin server for this fragment is busy and cannot accept new requests
     now. This is caused by Oracle Web Cache-to-origin server request queue
    limit.
  </esi:except>
  <esi:except type="networktimeout" >
     This is thrown by a fragment whose request to the origin server has timed
     out in the network connection. 
  </esi:except>
  <esi:except type="incorrectesifragment" >
     An error is encountered when Oracle Web Cache tries to parse or process
     the ESI fragment response body due to errors in the body.
  </esi:except>
  <esi:except>
     Unknown ESI Exception
  </esi:except>
</esi:try>

11.4.9 ESI vars Tag

The <esi:vars> tag enables you to use variables outside of ESI tags. For example, instead of specifying a variable inside a <esi:include> or <esi:choose> block, you can use the <esi:vars> tag to specify a variable inside HTML code.

11.4.9.1 Syntax

<esi:vars>Optional HTML code $(VARIABLE_NAME{key}) Optional HTML code</esi:vars>

11.4.9.2 Syntax Usage

  • If the variable does not use the complete $(VARIABLE_NAME{key}) format, Oracle Web Cache reports the following error message to the event log:

    [Date] [error 12086] [ecid: request_id, serial_number]ESI syntax error. Unrecognized keyword keyword is at line line.
    
  • Do not nest the <esi:vars> tag within an HTML code line. The following is an example of incorrect syntax:

    HTML code <esi:vars>$(VARIABLE_NAME{key})</esi:vars>HTML code
    

    For example, the following is invalid:

    <IMG SRC="http://www.example.com/<esi:vars>$(HTTP_COOKIE{type})</esi:vars>/hello.gif"/>
    

11.4.9.3 Usage

Section 11.1.6 and Section 11.4.3 for usage of HTTP request variables and custom variables

11.4.9.4 Example

The following ESI markup includes the cookie type and its value as part of the included URL:

<esi:vars>
  <IMG SRC="http://www.example.com/$(HTTP_COOKIE{type})/hello.gif"/>
</esi:vars>

The following ESI output refers to logindata as part of the <A HREF=...> link for the Welcome page. logindata refers to an XML file that contains custom environment variables. The output also includes the user's sessionID and category type cookie values as part of the other <A HREF=...> links.

<esi:vars>
  <A HREF="welcome.jsp?name=$(logindata{name})">
  <A HREF="/shopping.jsp?sessionID=$(QUERY_STRING{sessionID})&type=$(QUERY_STRING{type})">
  <IMG SRC="/img/shopping.gif">
  </A>
  <A HREF="/news.jsp?sessionID=$(QUERY_STRING{sessionID})&type=$(QUERY_STRING{type})">
  <IMG SRC="/img/news.gif">
  </A>
  <A HREF="/sports.jsp?sessionID=$(QUERY_STRING{sessionID})&type=$(QUERY_STRING{type})">
  <IMG SRC="/img/sports.gif">
  </A>
  <A HREF="/fun.jsp?sessionID=$(QUERY_STRING{sessionID})&type=$(QUERY_STRING{type})">
  <IMG SRC="/img/fun.gif">
  </A>
  <A HREF="/about.jsp?sessionID=$(QUERY_STRING{sessionID})&type=$(QUERY_STRING{type})">
  <IMG SRC="/img/about.gif">
  </A>
 </esi:vars>

11.4.10 ESI <!--esi-->Tag

The <!--esi...---> tag enables HTML marked up with ESI tags to display to the browser without processing the ESI tags. When a page is processed with this tag, Oracle Web Cache removes the starting <!--esi and ending --> elements, while still processing the contents of the page. When the markup cannot be processed, this tag assures that the ESI markup does not interfere with the final HTML output.

11.4.10.1 Syntax

<!--esi
 ESI elements
-->

11.4.10.2 Usage

Any ESI or HTML elements can be included within this tag, except other <!--esi...--> tags.

11.4.10.3 Example

In the following ESI markup, the <!--esi and --> are removed in the final
output. The output displays the content generated by <p><esi:vars>Hello, $(HTTP_COOKIE{name})!</esi:vars></p>, 
plus any surrounding text.

<!--esi  
 <p><esi:vars>Hello, $(HTTP_COOKIE{name})!</esi:vars></p>
-->

If the ESI markup cannot be processed, then the <p><esi:vars>Hello, $(HTTP_COOKIE{name})!</esi:vars></p> is displayed in the HTML output.