Product Documentation

Policy Extensions - Use Cases

Aug 31, 2016

Certain customer applications have requirements that cannot be addressed with existing policies and expressions. The policy extension feature enables customers to add customized functions to their applications to meet their requirement.

The following use cases illustrate the addition of new functions using the policy extension feature on the NetScaler appliance.

Case 1: Custom Hash

The CUSTOM_HASH function provides a mechanism to insert any type of hash value in the responses sent to the client. In this use case, the hash function is used to compute the hash of the query string for a rewrite HTTP request and insert an HTTP header named CUSTOM_HASH with the computed value. The CUSTOM_HASH function implements the DJB2 hash algorithm.

Sample Usage of CUSTOM_HASH 복사

> add rewrite action test_custom_hash insert_http_header "CUSTOM_HASH" "HTTP.REQ.URL.QUERY.CUSTOM_HASH"

Sample Definition of CUSTOM_HASH() 복사

-- Extension function to compute custom hash on the text
-- Uses the djb2 string hash algorithm

    local hash = 5381
    local len = string.len(self)
    for i = 1, len do
         hash = bit32.bxor((hash * 33), string.byte(self, i))
    return tostring(hash)

Line-by-line description of the above sample

Case 2: Collapse Double Slashes in URLs

Collapsing double slashes in URLs improves the website rendering time, because browsers parse the single slash URLs more efficiently. The single slash URLs also to maintain compatibility with applications that do not accept double slashes. The policy extension feature allows customers to add a function that replaces the double slashes with single slashes in the URLs. The following example illustrates the addition of a policy extension function that that collapses double slashes in URLs.

Sample Definition of COLLAPSE_DOUBLE_SLASHES() 복사

-- Collapse double slashes in URL to a single slash and return the result

    local result = string.gsub(self, "//", "/")
    return result

Line-by-line description of the above sample

Case 3: Combine Headers

Certain customer applications cannot handle multiple headers in a request. Also, parsing of duplicate headers with same header values, or multiple headers with same name but different values in a request, consumes time and network resources. The policy extension feature allows customers to add a function to combine these headers into single headers with a value combining the original values. For example, combining the values of the headers H1 and H2.

Original Request:

GET /combine_headers HTTP/1.1
User-Agent: amigo unit test
Host: myhost
H2: h2val1
H1: abcd
Accept: */*
H2: h2val2
Content-Length: 0
H2: h2val3
H1: 1234

Modified Request:

GET /combine_headers HTTP/1.1
User-Agent: amigo unit test
Host: myhost
H2: h2val1, h2val2, h2val3
H1: abcd, 1234
Accept: */*
Content-Length: 0

In general, this type of request modification is done using the Rewrite feature, using policy expressions to delineate the part of the request to be modified (the target) and the modification to be performed (the string builder expression). However, policy expressions do not have the ability to iterate over an arbitrary number of headers.

The solution to this problem requires an extension to the policy facility. To do this, we will define an extension function, called COMBINE_HEADERS. With this function, we can set up the following rewrite action:

> add rewrite action combine_headers_act replace 'HTTP.REQ.FULL_HEADER.AFTER_STR("HTTP/1.1\r\n")' 'HTTP.REQ.FULL_HEADER.AFTER_STR("HTTP/1.1\r\n").COMBINE_HEADERS'

Here, the rewrite target is HTTP.REQ.FULL_HEADER.AFTER_STR("HTTP/1.1\r\n"). The AFTER_STR("HTTP/1.1\r\n") is required because FULL_HEADER includes the first line of the HTTP request (e.g. GET /combine_headers HTTP/1.1).

The string builder expression is HTTP.REQ.FULL_HEADER.AFTER_STR("HTTP/1.1\r\n").COMBINE_HEADERS, where the headers (minus the first line) are fed into the COMBINE_HEADERS extension function, which combines and returns the values for headers.

Sample Definition of COMBINE_HEADERS() 복사

-- Extension function to combine multiple headers of the same name into one header.

    local headers = {} -- headers
    local combined_headers = {} -- headers with final combined values

    -- Iterate over each header (format "name:value\r\n")
    -- and build a list of values for each unique header name.
    for name, value in string.gmatch(self, "([^:]+):([^\r\n]*)\r\n") do
        if headers[name] then
            local next_value_index = #(headers[name]) + 1
            headers[name][next_value_index] = value
            headers[name] = {name .. ":" .. value}

    -- iterate over the headers and concat the values with separator ","
    for name, values in pairs(headers) do
        local next_header_index = #combined_headers + 1
        combined_headers[next_header_index] = table.concat(values, ",")

    -- Construct the result headers using table.concat()
    local result_str = table.concat(combined_headers, "\r\n") .. "\r\n\r\n"
    return result_str

Line-by-line description of the above sample