| .. Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| |
| .. include:: ../../../common.defs |
| |
| .. _developer-plugins-hooks-alternate-selection: |
| |
| HTTP Alternate Selection |
| ************************ |
| |
| 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 the ``TS_HTTP_SELECT_ALT_HOOK``, then it will be |
| called back when Traffic Server performs alternate selection. You cannot |
| register locally to the hook ``TS_HTTP_SELECT_ALT_HOOK`` by using |
| ``TSHttpTxnHookAdd`` - you can only do so by using only |
| ``TSHttpHookAdd``. 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 |
| ``TS_HTTP_SELECT_ALT_HOOK``. Traffic Server calls each of the select |
| alternate hooks with the ``TS_EVENT_HTTP_SELECT_ALT`` event. The |
| ``void *edata`` argument that is passed to the continuation is a pointer |
| to an ``TSHttpAltInfo`` 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 ``TSHttpAltInfoQualitySet``. |
| |
| .. note:: |
| |
| HTTP SM does not have to be re-enabled using ``TSHttpTxnReenable`` or any |
| other APIs; just return from the function. |
| |
| The sample code below shows how to call the alternate APIs. |
| |
| .. code-block:: c |
| |
| static void handle_select_alt(TSHttpAltInfo infop) |
| { |
| TSMBuffer client_req_buf, cache_resp_buf; |
| TSMLoc client_req_hdr, cache_resp_hdr; |
| |
| TSMLoc accept_transform_field; |
| TSMLoc 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 */ |
| TSHttpAltInfoClientReqGet (infop, &client_req_buf, &client_req_hdr); |
| TSHttpAltInfoCachedRespGet(infop, &cache_resp_buf, &cache_resp_hdr); |
| |
| /* get the Accept-Transform field value from the client request */ |
| accept_transform_field = TSMimeHdrFieldFind(client_req_buf, |
| client_req_hdr, "Accept-Transform", -1); |
| if (accept_transform_field) { |
| TSMimeHdrFieldValueStringGet(client_req_buf, client_req_hdr, |
| accept_transform_field, 0, &accept_transform_value, &accept_transform_len); |
| TSDebug(DBG_TAG, "Accept-Transform = |%s|", |
| accept_transform_value); |
| } |
| |
| /* get the Content-Transform field value from cached server response */ |
| content_transform_field = TSMimeHdrFieldFind(cache_resp_buf, |
| cache_resp_hdr, "Content-Transform", -1); |
| if (content_transform_field) { |
| TSMimeHdrFieldValueStringGet(cache_resp_buf, cache_resp_hdr, |
| content_transform_field, 0, &content_transform_value, &content_transform_len); |
| TSDebug(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; |
| } |
| |
| TSDebug(DBG_TAG, "Setting quality to %3.1f", quality); |
| |
| /* set quality for this alternate */ |
| TSHttpAltInfoQualitySet(infop, quality); |
| |
| /* cleanup */ |
| if (accept_transform_field) |
| TSHandleMLocRelease(client_req_buf, client_req_hdr, |
| accept_transform_field); |
| TSHandleMLocRelease(client_req_buf, TS_NULL_MLOC, client_req_hdr); |
| |
| if (content_transform_field) |
| TSHandleMLocRelease(cache_resp_buf, cache_resp_hdr, |
| content_transform_field); |
| TSHandleMLocRelease(cache_resp_buf, TS_NULL_MLOC, cache_resp_hdr); |
| } |
| |
| static int alt_plugin(TSCont contp, TSEvent event, void *edata) |
| { |
| TSHttpAltInfo infop; |
| |
| switch (event) { |
| case TS_EVENT_HTTP_SELECT_ALT: |
| infop = (TSHttpAltInfo)edata; |
| handle_select_alt(infop); |
| break; |
| |
| default: |
| break; |
| } |
| |
| return 0; |
| } |
| |
| void TSPluginInit (int argc, const char *argv[]) |
| { |
| TSHttpHookAdd(TS_HTTP_SELECT_ALT_HOOK, TSContCreate (alt_plugin, |
| NULL)); |
| } |
| |
| Traffic Server augments the alternate selection through these callouts |
| using the following algorithm: |
| |
| 1. 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. |
| |
| 2. Traffic Server then calls out each of the continuations on the global |
| ``TS_HTTP_SELECT_ALT_HOOK``'s list. |
| |
| 3. 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. |
| |
| 4. 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: |
| |
| - `TSHttpAltInfoCachedReqGet <http://people.apache.org/~amc/ats/doc/html/ts_8h.html#af4f3a56716e3e97afd582c7fdb14bcb7>`_ |
| |
| - `TSHttpAltInfoCachedRespGet <http://people.apache.org/~amc/ats/doc/html/ts_8h.html#aff5861ae4a4a7a6ce7b2d669c113b3bb>`_ |
| |
| - `TSHttpAltInfoClientReqGet <http://people.apache.org/~amc/ats/doc/html/ts_8h.html#a74d494c6442b6012d8385e92f0e14dee>`_ |
| |
| - `TSHttpAltInfoQualitySet <http://people.apache.org/~amc/ats/doc/html/ts_8h.html#a978b7160a048491d5698e0f4c0c79aad>`_ |