Richtlinienerweiterungen - Anwendungsfälle
Bestimmte Kundenanwendungen haben Anforderungen, die mit bestehenden Richtlinien und Ausdrücken nicht erfüllt werden können. Mit der Funktion zur Richtlinienerweiterung können Kunden ihren Anwendungen maßgeschneiderte Funktionen hinzufügen, um ihren Anforderungen gerecht zu werden.
Die folgenden Anwendungsfälle veranschaulichen das Hinzufügen neuer Funktionen mithilfe der Richtlinienerweiterungsfunktion auf der NetScaler-Appliance.
- Fall 1: Benutzerdefinierter Hash
- Fall 2: Doppelte Schrägstriche in URLs zusammenfassen
- Fall 3: Header kombinieren
Fall 1: Benutzerdefinierter Hash
Die CUSTOM_HASH-Funktion bietet einen Mechanismus zum Einfügen eines beliebigen Hashwerts in die an den Client gesendeten Antworten. In diesem Anwendungsfall wird die Hash-Funktion verwendet, um den Hash der Abfragezeichenfolge für eine HTTP-Rewrite-Anfrage zu berechnen und einen HTTP-Header namens CUSTOM_HASH mit dem berechneten Wert einzufügen. Die Funktion CUSTOM_HASH implementiert den DJB2-Hash-Algorithmus.
Beispiel für die Verwendung von CUSTOM_HASH:
> add rewrite action test_custom_hash insert_http_header "CUSTOM_HASH" "HTTP.REQ.URL.QUERY.CUSTOM_HASH"
<!--NeedCopy-->
Beispieldefinition von CUSTOM_HASH ():
-- Extension function to compute custom hash on the text
-- Uses the djb2 string hash algorithm
function NSTEXT:CUSTOM_HASH() : NSTEXT
local hash = 5381
local len = string.len(self)
for i = 1, len do
hash = bit32.bxor((hash * 33), string.byte(self, i))
end
return tostring(hash)
end
<!--NeedCopy-->
Zeilenweise Beschreibung des obigen Beispiels:
function NSTEXT:CUSTOM_HASH() : NSTEXT
Defines the CUSTOM_HASH() function, with text input and a text return value.
local hash = 5381
local len = string.len(self)
Declares two local variables:
- hash. Accumulates the compute hash value and is seeded with the number 5381
- len. Sets to the length of the self input text string, using the built-in string.len() function.
for i = 1, len do
hash = bit32.bxor((hash * 33), string.byte(self, i))
end
Iterates through each byte of the input string and adds the byte to the hash. It uses the built-in string.byte() function to get the byte and the built-in bit32.bxor() function to compute the XOR of the existing hash value (multiplied by 33) and the byte.
return tostring(hash)
Calls the built-in tostring() function to convert the numeric hash value to a string and returns the string as the value of the function.
<!--NeedCopy-->
Fall 2: Doppelte Schrägstriche in URLs zusammenfassen
Das Zusammenklappen doppelter Schrägstriche in URLs verbessert die Renderzeit der Website, da Browser die URLs mit einem Schrägstrich effizienter analysieren. Die URLs mit einem Schrägstrich dienen auch dazu, die Kompatibilität mit Anwendungen zu gewährleisten, die keine doppelten Schrägstriche akzeptieren. Mit der Funktion zur Richtlinienerweiterung können Kunden eine Funktion hinzufügen, die die doppelten Schrägstriche in den URLs durch einfache Schrägstriche ersetzt. Das folgende Beispiel veranschaulicht das Hinzufügen einer Richtlinienerweiterungsfunktion, die doppelte Schrägstriche in URLs ausblendet.
Beispieldefinition für COLLAPSE_DOUBLE_SLASHES ():
-- Collapse double slashes in URL to a single slash and return the result
function NSTEXT:COLLAPSE_DOUBLE_SLASHES() : NSTEXT
local result = string.gsub(self, "//", "/")
return result
end
<!--NeedCopy-->
Zeilenweise Beschreibung des obigen Beispiels:
function NSTEXT:COLLAPSE_DOUBLE_SLASHES() : NSTEXT
Declares the COLLAPSE_DOUBLE_SLASHES() function with text input and return.
local result = string.gsub(self, "//", "/")
Declares a local variable named result and uses the built-in string.gsub() function to replace all double slashes with single slashes in the self input text.
The second parameter of string.gsub() is actually a regular expression pattern, although here a simple string is used for the pattern.
return result
Returns the resulting string.
<!--NeedCopy-->
Fall 3: Header kombinieren
Bestimmte Kundenanwendungen können nicht mehrere Header in einer Anfrage verarbeiten. Außerdem verbraucht das Parsen doppelter Header mit denselben Header-Werten oder mehrerer Header mit demselben Namen, aber unterschiedlichen Werten in einer Anfrage Zeit und Netzwerkressourcen. Mit der Funktion zur Richtlinienerweiterung können Kunden eine Funktion hinzufügen, um diese Header zu einzelnen Headern zu kombinieren, wobei ein Wert die ursprünglichen Werte kombiniert. Kombinieren Sie beispielsweise die Werte der Header H1 und H2.
Ursprüngliche Anfrage:
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
<!--NeedCopy-->
Geänderte Anfrage:
GET /combine_headers HTTP/1.1
User-Agent: amigo unit test
Host: myhost
H2: h2val1, h2val2, h2val3
H1: abcd, 1234
Accept: \*/\*
Content-Length: 0
<!--NeedCopy-->
Im Allgemeinen erfolgt diese Art der Anforderungsänderung mithilfe der Rewrite-Funktion, wobei Richtlinienausdrücke verwendet werden, um den Teil der Anfrage, der geändert werden soll (das Ziel), und die durchzuführende Änderung (der String-Builder-Ausdruck) abzugrenzen. Richtlinienausdrücke sind jedoch nicht in der Lage, über eine beliebige Anzahl von Headern zu iterieren.
Die Lösung dieses Problems erfordert eine Erweiterung der politischen Fazilität. Dazu definieren wir eine Erweiterungsfunktion namens COMBINE_HEADERS. Mit dieser Funktion können wir die folgende Rewrite-Aktion einrichten:
> add rewrite action combine_headers_act replace 'HTTP.REQ.FULL_HEADER.AFTER_STR("HTTP/1.1rn")' 'HTTP.REQ.FULL_HEADER.AFTER_STR("HTTP/1.1rn").COMBINE_HEADERS'
Hier ist das Rewrite-Ziel HTTP.REQ.FULL_HEADER.AFTER_STR („http/1.1RN“). AFTER_STR („http/1.1Rn“) ist erforderlich, da FULL_HEADER die erste Zeile der HTTP-Anfrage enthält (z. B. GET /combine_headers HTTP/1.1).
Der String-Builder-Ausdruck ist HTTP.REQ.FULL_HEADER.AFTER_STR(“HTTP/1.1rn”).COMBINE_HEADERS, wobei die Header (abzüglich der ersten Zeile) in die Erweiterungsfunktion COMBINE_HEADERS eingegeben werden, die die Werte für Header kombiniert und zurückgibt.
Beispieldefinition von COMBINE_HEADERS ():
-- Extension function to combine multiple headers of the same name into one header.
function NSTEXT:COMBINE_HEADERS(): NSTEXT
local headers = {} -- headers
local combined_headers = {} -- headers with final combined values
-- Iterate over each header (format "name:valuer\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
else
headers[name] = {name .. ":" .. value}
end
end
-- 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, ",")
end
-- Construct the result headers using table.concat()
local result_str = table.concat(combined_headers, "\r\n") .. "\r\n\r\n"
return result_str
end
<!--NeedCopy-->
Zeilenweise Beschreibung des obigen Beispiels:
function NSTEXT:COMBINE_HEADERS(): NSTEXT
Defines the COMBINE_HEADERS extension function, with the text input into the function from the policy expression and a text return type to the policy expression.
local headers = {} -- headers
local combined_headers = {} -- headers with final combined values
Declares local variables headers and combined_headers and initialize these variables to empty tables. headers will be a table of arrays of strings, where each array holds one or more values for a header. combined_headers will be an array of strings, where each array element is a header with its combined values.
for name, value in string.gmatch(self, "([^:]+):([^\r\n]*)\r\n") do
. . .
end
<!--NeedCopy-->
Dieses generische For-Loop analysiert jeden Header in der Eingabe. Der Iterator ist die integrierte Funktion string.gmatch(). Diese Funktion benötigt zwei Parameter: eine zu durchsuchende Zeichenfolge und ein Muster, das verwendet wird, um Teile der Zeichenfolge abzugleichen. Die zu durchsuchende Zeichenfolge wird vom impliziten Parameter self bereitgestellt, der der Text für die in die Funktion eingegebenen Header ist.
Das Muster wird mit einem regulären Ausdruck (kurz Regex) ausgedrückt. Dieser Regex entspricht dem Header-Namen und -Wert für jeden Header, den der HTTP-Standard als *name*:value\r\n definiert. Die Klammern im Regex geben die passenden Teile an, die extrahiert werden sollen. Das Regex-Schema lautet also (match-name):(match-value)\r\n. Das Match-Name-Muster muss mit allen Zeichen außer dem Doppelpunkt übereinstimmen. Das steht geschrieben [^:]+
. [^:]
ist ein beliebiges Zeichen außer :
und +
ist eine oder mehrere Wiederholungen. In ähnlicher Weise muss das Match-Value-Muster mit allen Zeichen außer dem \r\n
übereinstimmen, daher wird es so geschrieben: [^\r\n]*
. [^\r\n]
entspricht allen Zeichen außer \r
und \n
, und *
ist null oder mehr Wiederholungen. Das ergibt den kompletten Regex ([^:]+):([^\r\n]*)\r\n
.
Die for -Anweisung verwendet eine Mehrfachzuweisung, um Namen und Wert für die beiden Treffer festzulegen, die vom Iterator string.gmatch () zurückgegeben werden. Diese werden implizit als lokale Variablen im Hauptteil der for-Schleife deklariert.
if headers[name] then
local next_value_index = #(headers[name]) + 1
headers[name][next_value_index] = value
else
headers[name] = {name .. ":" .. value}
end
<!--NeedCopy-->
Diese Anweisungen innerhalb der for-Schleife setzen die Headernamen und -werte in die Header-Tabelle. Wenn ein Header-Name zum ersten Mal analysiert wird (sagen wir H2: h2val1 in der Beispieleingabe), gibt es keinen Headereintrag für den Namen und headers [name] ist Null.
Da nil als falsch behandelt wird, wird die else-Klausel ausgeführt. Dies setzt den Header-Eintrag für name auf ein Array mit einem Zeichenfolgenwert name:value.
Hinweis: Der Array-Konstruktor in der Else-Schleife entspricht {[1] = name.. “:”.. value}, wodurch das erste Element des Arrays festgelegt wird.) Für den ersten H2-Header wird headers[“H2”] = {“H2:h2val1”} festgelegt.
Bei nachfolgenden Instanzen eines Headers (sagen wir H2: h2val2 in der Beispieleingabe). headers[name] ist nicht null, daher wird die Then-Klausel ausgeführt. Dies bestimmt den nächsten verfügbaren Index im Array-Wert für Header [Name] und fügt den Header-Wert in diesen Index ein. Für den zweiten H2-Header wird headers[“H2”] = {“H2:h2val1”, “h2val2”} festgelegt.
for name, values in pairs(headers) do
local next_header_index = #combined_headers + 1
combined_headers[next_header_index] = table.concat(values, ",")
end
<!--NeedCopy-->
Nachdem die ursprünglichen Header analysiert und die Header-Tabelle ausgefüllt wurden, erstellt diese Schleife das Array combined_headers. Es verwendet die Funktion pairs () als For-Loop-Iterator.
Jeder Aufruf von pairs () gibt den Namen und Wert des nächsten Eintrags in der Header-Tabelle zurück.
Die nächste Zeile bestimmt den nächsten verfügbaren Index im Array combined_headers, und die nächste Zeile setzt dieses Array-Element auf den kombinierten Header. Es verwendet die eingebaute Funktion table.concat (), die als Argumente ein Array von Zeichenketten und eine Zeichenfolge verwendet, die als Trennzeichen verwendet wird, und eine Zeichenfolge zurückgibt, die die Verkettung der Array-Zeichenketten darstellt, getrennt durch das Trennzeichen.
Beispielsweise ergibt dies für Werte = {“h2:h2val1”, „h2val2”} „h2:h2val1, h2val2“
local result_str = table.concat(combined_headers, "\r\n") .. "\r\n\r\n"
<!--NeedCopy-->
Nachdem das Array combined_headers erstellt wurde, verkettet es die Elemente zu einer Zeichenfolge und fügt ein doppeltes\ r\ n hinzu, das die HTTP-Header beendet.
return result_str
<!--NeedCopy-->
Gibt eine Zeichenfolge als Ergebnis der Erweiterungsfunktion COMBINE_HEADERS zurück.