The HTTP alternate selection functions provide a mechanism for hooking into Traffic Server’s alternate selection mechanism and augmenting it with additional information. HTTP alternate selection refers to the process of choosing between several alternate versions of a document for a specific URL. Alternates arise because the HTTP 1.1 specification allows different documents to be sent back for the same URL (depending on the clients request). For example, a server might send back a GIF image to a client that only accepts GIF images, and might send back a JPEG image to a client that only accepts JPEG images.
The alternate selection mechanism is invoked when Traffic Server looks up a URL in its cache. For each URL, Traffic Server stores a vector of alternates. For each alternate in this vector, Traffic Server computes a quality value between 0 and 1 that represents how “good” the alternate is. A quality value of 0 means that the alternate is unacceptable; a value of 1 means that the alternate is a perfect match.
If a plugin hooks onto theINK_HTTP_SELECT_ALT_HOOK
, then it
will be called back when Traffic Server performs alternate selection.
You cannot register locally to the hook
INK_HTTP_SELECT_ALT_HOOK
by using INKHttpTxnHookAdd
- you can only do so by
using only INKHttpHookAdd
. Since Traffic Server does not
actually have an HTTP transaction or an HTTP session on hand when
alternate selection is performed, it is only valid to hook onto the global list
of INK_HTTP_SELECT_ALT_HOOK
. Traffic Server calls each of the
select alternate hooks with the INK_EVENT_HTTP_SELECT_ALT
event. The void *edata
argument
that is passed to the continuation is a pointer to an INKHttpAltInfo
structure. It can be used later to call the HTTP
alternate selection functions listed at the end of this section. Unlike
other hooks, this alternate selection callout is non-blocking; the
expectation is that the quality value for the alternate will be changed
by a call to INKHttpAltInfoQualitySet
.
![]() |
Note |
---|---|
HTTP SM does not have to be reenabled using
|
The sample code below shows how to call the alternate APIs.
static void handle_select_alt(INKHttpAltInfo infop) { INKMBuffer client_req_buf, cache_resp_buf; INKMLoc client_req_hdr, cache_resp_hdr; INKMLoc accept_transform_field; INKMLoc content_transform_field; int accept_transform_len = -1, content_transform_len = -1; const char* accept_transform_value = NULL; const char* content_transform_value = NULL; int content_plugin, accept_plugin; float quality; /* get client request, cached request and cached response */ INKHttpAltInfoClientReqGet (infop, &client_req_buf, &client_req_hdr); INKHttpAltInfoCachedRespGet(infop, &cache_resp_buf, &cache_resp_hdr); /* get the Accept-Transform field value from the client request */ accept_transform_field = INKMimeHdrFieldFind(client_req_buf, client_req_hdr, "Accept-Transform", -1); if (accept_transform_field) { INKMimeHdrFieldValueStringGet(client_req_buf, client_req_hdr, accept_transform_field, 0, &accept_transform_value, &accept_transform_len); INKDebug(DBG_TAG, "Accept-Transform = |%s|", accept_transform_value); } /* get the Content-Transform field value from cached server response */ content_transform_field = INKMimeHdrFieldFind(cache_resp_buf, cache_resp_hdr, "Content-Transform", -1); if (content_transform_field) { INKMimeHdrFieldValueStringGet(cache_resp_buf, cache_resp_hdr, content_transform_field, 0, &content_transform_value, &content_transform_len); INKDebug(DBG_TAG, "Content-Transform = |%s|", content_transform_value); } /* compute quality */ accept_plugin = (accept_transform_value && (accept_transform_len > 0) && (strncmp(accept_transform_value, "plugin", accept_transform_len) == 0)); content_plugin = (content_transform_value && (content_transform_len >0) && (strncmp(content_transform_value, "plugin", content_transform_len) == 0)); if (accept_plugin) { quality = content_plugin ? 1.0 : 0.0; } else { quality = content_plugin ? 0.0 : 0.5; } INKDebug(DBG_TAG, "Setting quality to %3.1f", quality); /* set quality for this alternate */ INKHttpAltInfoQualitySet(infop, quality)/ /* cleanup */ if (accept_transform_value) INKHandleStringRelease(client_req_buf, accept_transform_field, accept_transform_value); if (accept_transform_field) INKHandleMLocRelease(client_req_buf, client_req_hdr, accept_transform_field); INKHandleMLocRelease(client_req_buf, INK_NULL_MLOC, client_req_hdr); if (content_transform_value) INKHandleStringRelease(cache_resp_buf, content_transform_field, content_transform_value); if (content_transform_field) INKHandleMLocRelease(cache_resp_buf, cache_resp_hdr, content_transform_field); INKHandleMLocRelease(cache_resp_buf, INK_NULL_MLOC, cache_resp_hdr); } static int alt_plugin(INKCont contp, INKEvent event, void *edata) { INKHttpAltInfo infop; switch (event) { case INK_EVENT_HTTP_SELECT_ALT: infop = (INKHttpAltInfo)edata; handle_select_alt(infop); break; default: break; } return 0; } void INKPluginInit (int argc, const char *argv[]) { INKHttpHookAdd(INK_HTTP_SELECT_ALT_HOOK, INKContCreate (alt_plugin, NULL)); }
Traffic Server augments the alternate selection through these callouts using the following algorithm:
Traffic Server computes its own quality value for the alternate, taking into account the quality of the accept match, the encoding match, and the language match.
Traffic Server then calls out each of the continuations on the
global INK_HTTP_SELECT_ALT_HOOK
’s list.
It multiplies its quality value with the value returned by each callout. Since all of the values are clamped to be between 0 and 1, the final value will be between 0 and 1 as well.
This algorithm also ensures that a single callout can block the usage of a given alternate by specifying a quality value of 0.
A common usage for the alternate selection mechanism is when a plugin transforms a document for some clients and not for others, but wants to store both the transformed and unchanged document. The client’s request will specify whether it accepted the transformed document. The plugin will then determine if the alternate matches this specification and then set the appropriate quality level for the alternate.
The HTTP alternate selection functions are: