Fortinet black logo

Handbook

Examples

Examples

This section provides example scripts for common use cases. It includes the following examples:

Tip: The examples show debug strings. Debug strings can be written to the console when the event is triggered. This is helpful when you are testing your scripts.

To enable debug strings to be written to the console, use the following CLI commands:

diagnose debug enable

diagnose debug module httproxy scripting

Select content routes based on URI string matches

The content routing feature has rules that match HTTP requests to content routes based on a Boolean AND combination of match conditions. If you want to select routes based on a Boolean OR, you can configure multiple rules. The content routing rules table is consulted from top to bottom until one matches.

In some cases, it might be simpler to get the results you want using a script. In the following example, each rule selects content routes based on OR match conditions.

Content routing example

when RULE_INIT {

debug("get header init 1\n")

}

when HTTP_REQUEST{

uri = HTTP:uri_get()

if uri:find("sports") or uri:find("news") or uri:find("government") then

LB:routing("sp2")

debug("uri %s matches sports|news|government\n", uri);

elseif uri:find("finance") or uri:find("technology") or uri:find("shopping") then

LB:routing("sp3")

debug("uri %s matches finance|technology|shopping\n", uri);

elseif uri:find("game") or uri:find("bbs") or uri:find("testing") then

LB:routing("sp4")

debug("uri %s matches game|bbs|testing\n", uri);

elseif uri:find("billing") or uri:find("travel") or uri:find("weibo") then

LB:routing("sp5")

debug("uri %s matches billing|travel|weibo\n", uri);

else

debug("no matches for uri: %s \n", uri);

end

}

To use a script for content routing:
  1. Create the content route configuration objects. In the example above, sp2, sp3, sp4, and sp4 are the names of the content route configuration objects. You do not need to configure matching conditions for the content routes, however, because the script does the content matching.
  2. Create a script that matches content to the content route configuration objects, as shown above. Create a configuration object for the script.
  3. In the virtual server configuration:
    1. Enable content routing and select the content route configuration objects.
    2. Select the script.

Rewrite the HTTP request host header and path

You can use the content rewriting feature to rewrite the HTTP request Host header or the HTTP request URL. If you need more granular capabilities, you can use scripts. The following example rewrites the HTTP Host header and path.

Rewrite the HTTP Host header and path in a HTTP request

when RULE_INIT {

debug("rewrite the HTTP Host header and path in a HTTP request \n")

}

when HTTP_REQUEST{

host = HTTP:header_get_value("Host")

path = HTTP:path_get()

if host:lower():find("myold.hostname.com") then

debug("found myold.hostname.com in Host %s \n", host)

HTTP:header_replace("Host", "mynew.hostname.com")

HTTP:path_set("/other.html")

end

}

Note: You might find it useful to use a combination of string manipulation functions. For example, this script uses lower() to convert the Host strings to lowercase in combination with find(), which searches for the Host header for a match: host:lower():find("myold.hostname.com").

Rewrite the HTTP response Location header

You can use the content rewriting feature to rewrite the HTTP response Location header. If you are more comfortable using Lua string substitution, you can write a script to get the results you want. The following example rewrites the HTTP response Location header.

Rewrite the HTTP body in the response

when RULE_INIT {

debug("rewrite the HTTP response replacing myold.hostname.com with mynew.hostname.com \n")

}

when HTTP_RESPONSE{

location = HTTP:header_get_value("Location")

if location:lower():find("myold.hostname.com") then

debug("found myold.hostname.com in Location %s \n", location)

HTTP:header_replace("Location", "mynew.hostname.com")

end

}

Redirect HTTP to HTTPS using Lua string substitution

You can use the content rewriting feature to redirect an HTTP request to an HTTPS URL that has the same host and request URL using a PCRE regular expression. If you are more comfortable using Lua string substitution, you can write a script to get the results you want. The following example redirects users to the HTTPS location.

Redirect HTTP to HTTPS

when RULE_INIT {

debug("http to https redirect\n")

}

when HTTP_REQUEST{

host = HTTP:header_get_value("Host")

path = HTTP:path_get()

HTTP:redirect("https://%s%s",host,path);

}

Redirect mobile users to the mobile version of a website

The content rewriting feature does not support matching the User-Agent header. You can write a script that detects User-Agent headers that identify mobile device users and redirect them to the mobile version of a website.

Redirect mobile users to the mobile version of a website by parsing the User-Agent header

when RULE_INIT {

debug("detect User-Agent and go to mobile site\n")

}

when HTTP_REQUEST{

path = HTTP:path_get()

debug("path=%s\n",path)

agent = HTTP:header_get_value("User-Agent")

if agent:lower():find("iphone") or agent:lower():find("ipad") then

debug("found iphone or ipad in User-Agent %s \n", agent)

HTTP:redirect("https://m.mymobilesite.com%s",path)

end

}

Insert random message ID into a header

FortiADC offers the feature to insert messages and message IDs into HTTP request headers.

when HTTP_REQUEST{

ID=HTTP:rand_id()-- a 32-long string of HEX symbols

HTTP:header_insert("Message-ID",ID)

}

General HTTP redirect

You can redirect both HTTP requests and HTTP responses to a given location.

GENERAL_REDIRECT_DEMO:

when HTTP_REQUEST{

--can be used in both HTTP_REQUEST and HTTP_RESPONSE

--code and cookie are optional, code can be 301, 302, 303, 307, 308, if missed, 302 is used

t={}

t["code"] = 302;

t["url"] = "www.example.com"

t["cookie"] = "name=value; Expires=Wed, 09 Jun 2021 10:18:14 GMT"

HTTP:redirect_t(t);

}

Use request headers in other events

You can get stored request headers by using the session ID.

when RULE_INIT{

--initialize the global so-called "environment" variable

env={}

}

when HTTP_REQUEST{

sess_id = HTTP:get_session_id()

req={}

--store whatever you want to req, take url as an example

req["url"] = HTTP_uri_get()

env[id] = req

}

when HTTP_RESPONSE{

sess_id = HTTP:get_session_id()

req = env[id]

--now you can access the stored request headers

debug("my stored request url is %s\n", req["url"]);

}

when HTTP_DATA_REQUEST{

sess_id = HTTP:get_session_id()

req = env[id]

--now you can access the stored request headers

debug("my stored request url is %s\n", req["url"]);

}

when HTTP_DATA_RESPONSE{

sess_id = HTTP:get_session_id()

req = env[id]

--now you can access the stored request headers

debug("my stored request url is %s\n", req["url"]);

}

Compare IP address to address group

You can compare IP addresses to an internal list of IP addresses. The script will return different results signifying whether the IP is in the list.

when RULE_INIT{

--initialize the address group here

--for IPv4 address, mask can be a number between 0 to 32 or a dotted format

--support both IPv4 and IPv6, for IPv6, the mask is a number between 0 and 128

addr_group = "192.168.1.0/24"

addr_group = addr_group..",172.30.1.0/255.255.0.0"

addr_group = addr_group..",::ffff:172.40.1.0/120"

}

when HTTP_REQUEST{

client_ip = HTTP:client_addr()

matched = cmp_addr(client_ip, addr_group)

if matched then

debug("client ip found in address group\n");

else

debug("client ip not in address group\n");

end

}

Redirect HTTP to HTTPS

You can redirect an HTTP request from an HTTP location to an HTTPS location.

when HTTP_REQUEST{

Host = HTTP:header_get_value("host")

Url = HTTP:uri_get()

HTTP:redirect("https://%s%s", Host, Url)

}

Rewrite HTTP to HTTPS in location

You can rewrite HTTP request headers to replace all HTTP addresses with HTTPS addresses in the redirect location.

when HTTP_RESPONSE{

loc = HTTP:header_get_value("Location")

if loc then

newloc = string.gsub(loc, "http", "https") --replace all http by https in the redirect location

HTTP:header_replace("Location", newloc);

end

}

Rewrite HTTP to HTTPS in referer

You can rewrite HTTP request headers to replace all HTTP addresses with HTTPS addresses in the redirect referer.

when HTTP_RESPONSE{

ref = HTTP:header_get_value("Referer")

if ref then

newref = string.gsub(ref, "http", "https") --replace all http by https in the referer header

HTTP:header_replace("Referer", newref);

end

}

Rewrite HTTPS to HTTP in location

You can rewrite HTTP request headers to replace all HTTPS addresses with HTTP addresses in the redirect location.

when HTTP_RESPONSE{

loc = HTTP:header_get_value("Location")

if loc then

newloc = string.gsub(loc, "https", "http") --replace all https by http in the redirect location

HTTP:header_replace("Location", newloc);

end

}

Rewrite HTTPS to HTTP in referer

You can rewrite HTTP request headers to replace all HTTPS addresses with HTTP addresses in the redirect referer.

when HTTP_RESPONSE{

ref = HTTP:header_get_value("Referer")

if ref then

newref = string.gsub(ref, "https", "http") --replace all https by http in the referer header

HTTP:header_replace("Referer", newref);

end

}

Fetch data from HTTP events

You can collect data from both HTTP request and HTTP response events. You can then manipulate this data.

when HTTP_REQUEST{

--HTTP:collect command can be used in both HTTP_REQUEST and HTTP_RESPONSE events

--size is optional, otherwise, it will collect up to the full length or when 1.25M is reached

t={}

t["size"] = 100;

HTTP:collect(t)

}

when HTTP_DATA_REQUEST{

--check the size of the content

t={};

t["operation"]="size";

sz=HTTP:payload(t);

debug("content size: %s\n", sz);

--fetch the collected content

--offset and size are optional

t={};

t["operation"]="content";

t["offset"] = 0;

t["size"] = sz;

ct=HTTP:payload(t);

debug("content: %s\n", ct);

--do your own manipulation on the collected content

--replace the collected content by your new data

--offset and size are optional

t={};

t["operation"]="set";

t["offset"] = 0;

t["size"] = sz;

t["data"]="NEW DATA to SEND";

ret = HTTP:payload(t);

debug("set ret %s\n", ret);

}

Replace HTTP body data

You can find, remove, and replace data in the body of an HTTP request.

when HTTP_REQUEST{

--HTTP:collect command can be used in both HTTP_REQUEST and HTTP_RESPONSE events

--size is optional, otherwise, it will collect up to the full length or when 1.25M is reached

t={}

t["size"] = 100;

HTTP:collect(t)

}

when HTTP_DATA_REQUEST{

--check the size of the content

t={};

t["operation"]="size";

sz=HTTP:payload(t);

debug("content size: %s\n", sz);

--find a string or a regular expression in the buffered data

--offset, size and scope are optional, if scope is missing, "all" is assumed

t={};

t["operation"]="find";

t["offset"] = 0;

t["size"] = sz;

t["scope"] = "all";-- or "first"

t["data"] = "your string or a regular expression to find";

if HTTP:payload(t) then

debug("found %d occurences\n", ret);

else

debug("not found\n");

end

--remove a string or a regular expression in the buffered data

--offset, size and scope are optional, if scope is missing, "all" is assumed

t={};

t["operation"]="remove";

t["offset"] = 0;

t["size"] = sz;

t["scope"] = "all";-- or "first"

t["data"] = "your string or a regular expression to find";

if HTTP:payload(t) then

debug("removed %d occurences\n", ret);

else

debug("not found\n");

end

--replace a string or a regular expression in the buffered data by a new string

--offset, size and scope are optional, if scope is missing, "all" is assumed

t={};

t["operation"]="replace";

t["offset"] = 0;

t["size"] = sz;

t["scope"] = "all";-- or "first"

t["data"] = "your string or a regular expression to find";

t["new_data"] = "your new data";

if HTTP:payload(t) then

debug("replaced %d occurences\n", ret);

else

debug("not found\n");

end

}

Persist

You can set the entry to the persist table and real server will be assigned after lookup

when RULE_INIT {

env={}

PROXY:init_stick_tbl_timeout(1000)

}

when PERSISTENCE {

debug("PERSIST \n");

t={};

t["operation"] = "get_valid_server";

ret_tbl = HTTP: persist(t);

if(ret_tbl) then

for srv, state in pairs(ret_tbl) do

debug("server %s status %s\n", srv, state);

end

end

t={};

t["operation"] = "save_tbl";

t["hash_value"]= "hash_str";

t["srv_name"]= "rsrv_70";

ret = HTTP: persist(t)

if ret then

debug("save table success\n");

else

debug("save table failed\n");

end

t={};

t["operation"] = "dump_tbl";

t["index"] = 0;

t["count"] = 500;

ret_tbl = HTTP: persist(t)

if(ret_tbl) then

for k, cnt in pairs(ret_tbl) do

debug(" hash %s srv_name %s\n", k, cnt)

end

end

t={};

t["hash_value"]= "hash_str";

ret = HTTP:lookup_tbl(t);

if ret then

debug("LOOKUP success\n");

else

debug("LOOKUP fail\n");

end

}

Post_persist

You can get the current assigned server in POST_PERSIT and assign real server you like by setting table and lookup in PERSISTENCE

when RULE_INIT {

env={}

PROXY:init_stick_tbl_timeout(1000)

}

when PERSISTENCE {

debug("PERSIST \n");

t={};

t["hash_value"]= "hash_str";

ret = HTTP:lookup_tbl(t);

if ret then

debug("LOOKUP success\n");

else

debug("LOOKUP fail\n");

end

}

when POST_PERSIST {

debug("POST PERSIST \n");

t={};

t["operation"] = "get_current_assigned_server"

ret_tbl = HTTP: persist(t)

if ret then

debug("assign to %s\n", ret_tbl);

else

debug("get_current_assigned_server failed\n");

end

t={};

t["operation"] = "save_tbl";

t["hash_value"]= "hash_str";

t["srv_name"]= "rsrv_70";

ret = HTTP: persist(t)

if ret then

debug("save table success\n");

else

debug("save table failed\n");

end

}

Run multiple scripts

You can run multiple scripts in FortiADC. When running multiple scripts, you may set a priority number for each script. FortiADC will run them in order from lowest priority to highest priority. The default priority is 500. if two scripts have the same priority number, they will be executed in the order in which they were added.

--script 1:

when HTTP_REQUEST priority 500 {

LB:routing(“cr1”)

}

--script 2:

when HTTP_RESPONSE priority 500 {

HTTP:close()

}

--script 3:

when HTTP_REQUEST priority 400 {

LB:routing(“cr2”)

}

--script 4:

when HTTP_RESPONSE priority 600 {

HTTP:close()

}

Prioritize scripts

While running multiple scripts, you can prioritize scripts. Add a priority number to each script when you create it, and FortiADC will run them in order from lowest priority to highest priority. The default priority is 500.If two scripts have the same priority number, they will be executed in the order in which they were added.

when RULE_INIT priority 14 {

--This is one of the script to demo the control of multiple scripts

--please change the priority of each event according to your need

debug("INIT in script 1\n");

}

when HTTP_REQUEST priority 12 {

debug("HTTP_REQUEST in script 1\n");

--add your own manipulation here

--you can disable rest of the HTTP_REQUEST events from executing by disabling this event

t={};

t["event"]="req"; -- can be "req", "res", "data_req", and "data_res"

t["operation"]="disable"; -- can be "enable", and "disable"

HTTP:set_event(t);

debug("disable rest of the HTTP_REQUEST events in script 1\n");

--you can also disable other events, say HTTP_RESPONSE, DATA events

--in the case of keep-alive, all events will be re-enabled automatically even though they are disabled in previous TRANSACTION using the HTTP:set_event(t) command. To disable this automatic re-enabling behavior, you can call HTTP:set_auto(t) as below

t={};

t["event"]="req"; -- can be "req", "res", "data_req", and "data_res"

t["operation"]="disable"; -- can be "enable", and "disable"

HTTP:set_auto(t);

debug("disable automatic re-enabling of the HTTP_REQUEST events in script 1\n");

--you can also disable automatic re-enabling for other events, say HTTP_RESPONSE, DATA events

}

or

when RULE_INIT priority 24 {

--This is one of the script to demo the control of multiple scripts

--please change the priority of each event according to your need

debug("INIT in script 2\n");

}

when HTTP_REQUEST priority 24 {

debug("HTTP_REQUEST in script 2\n");

--add your own manipulation here

--you can disable rest of the HTTP_REQUEST events from executing by disabling this event

t={};

t["event"]="req"; -- can be "req", "res", "data_req", and "data_res"

t["operation"]="disable"; -- can be "enable", and "disable"

HTTP:set_event(t);

debug("disable rest of the HTTP_REQUEST events in script 2\n");

--you can also disable other events, say HTTP_RESPONSE, DATA events

--in the case of keep-alive, all events will be re-enabled automatically even though they are disabled in previous TRANSACTION using the HTTP:set_event(t) command. To disable this automatic re-enabling behavior, you can call HTTP:set_auto(t) as below

t={};

t["event"]="req"; -- can be "req", "res", "data_req", and "data_res"

t["operation"]="disable"; -- can be "enable", and "disable"

HTTP:set_auto(t);

debug("disable automatic re-enabling of the HTTP_REQUEST events in script 2\n");

--you can also disable automatic re-enabling for other events, say HTTP_RESPONSE, DATA events

}

Examples

This section provides example scripts for common use cases. It includes the following examples:

Tip: The examples show debug strings. Debug strings can be written to the console when the event is triggered. This is helpful when you are testing your scripts.

To enable debug strings to be written to the console, use the following CLI commands:

diagnose debug enable

diagnose debug module httproxy scripting

Select content routes based on URI string matches

The content routing feature has rules that match HTTP requests to content routes based on a Boolean AND combination of match conditions. If you want to select routes based on a Boolean OR, you can configure multiple rules. The content routing rules table is consulted from top to bottom until one matches.

In some cases, it might be simpler to get the results you want using a script. In the following example, each rule selects content routes based on OR match conditions.

Content routing example

when RULE_INIT {

debug("get header init 1\n")

}

when HTTP_REQUEST{

uri = HTTP:uri_get()

if uri:find("sports") or uri:find("news") or uri:find("government") then

LB:routing("sp2")

debug("uri %s matches sports|news|government\n", uri);

elseif uri:find("finance") or uri:find("technology") or uri:find("shopping") then

LB:routing("sp3")

debug("uri %s matches finance|technology|shopping\n", uri);

elseif uri:find("game") or uri:find("bbs") or uri:find("testing") then

LB:routing("sp4")

debug("uri %s matches game|bbs|testing\n", uri);

elseif uri:find("billing") or uri:find("travel") or uri:find("weibo") then

LB:routing("sp5")

debug("uri %s matches billing|travel|weibo\n", uri);

else

debug("no matches for uri: %s \n", uri);

end

}

To use a script for content routing:
  1. Create the content route configuration objects. In the example above, sp2, sp3, sp4, and sp4 are the names of the content route configuration objects. You do not need to configure matching conditions for the content routes, however, because the script does the content matching.
  2. Create a script that matches content to the content route configuration objects, as shown above. Create a configuration object for the script.
  3. In the virtual server configuration:
    1. Enable content routing and select the content route configuration objects.
    2. Select the script.

Rewrite the HTTP request host header and path

You can use the content rewriting feature to rewrite the HTTP request Host header or the HTTP request URL. If you need more granular capabilities, you can use scripts. The following example rewrites the HTTP Host header and path.

Rewrite the HTTP Host header and path in a HTTP request

when RULE_INIT {

debug("rewrite the HTTP Host header and path in a HTTP request \n")

}

when HTTP_REQUEST{

host = HTTP:header_get_value("Host")

path = HTTP:path_get()

if host:lower():find("myold.hostname.com") then

debug("found myold.hostname.com in Host %s \n", host)

HTTP:header_replace("Host", "mynew.hostname.com")

HTTP:path_set("/other.html")

end

}

Note: You might find it useful to use a combination of string manipulation functions. For example, this script uses lower() to convert the Host strings to lowercase in combination with find(), which searches for the Host header for a match: host:lower():find("myold.hostname.com").

Rewrite the HTTP response Location header

You can use the content rewriting feature to rewrite the HTTP response Location header. If you are more comfortable using Lua string substitution, you can write a script to get the results you want. The following example rewrites the HTTP response Location header.

Rewrite the HTTP body in the response

when RULE_INIT {

debug("rewrite the HTTP response replacing myold.hostname.com with mynew.hostname.com \n")

}

when HTTP_RESPONSE{

location = HTTP:header_get_value("Location")

if location:lower():find("myold.hostname.com") then

debug("found myold.hostname.com in Location %s \n", location)

HTTP:header_replace("Location", "mynew.hostname.com")

end

}

Redirect HTTP to HTTPS using Lua string substitution

You can use the content rewriting feature to redirect an HTTP request to an HTTPS URL that has the same host and request URL using a PCRE regular expression. If you are more comfortable using Lua string substitution, you can write a script to get the results you want. The following example redirects users to the HTTPS location.

Redirect HTTP to HTTPS

when RULE_INIT {

debug("http to https redirect\n")

}

when HTTP_REQUEST{

host = HTTP:header_get_value("Host")

path = HTTP:path_get()

HTTP:redirect("https://%s%s",host,path);

}

Redirect mobile users to the mobile version of a website

The content rewriting feature does not support matching the User-Agent header. You can write a script that detects User-Agent headers that identify mobile device users and redirect them to the mobile version of a website.

Redirect mobile users to the mobile version of a website by parsing the User-Agent header

when RULE_INIT {

debug("detect User-Agent and go to mobile site\n")

}

when HTTP_REQUEST{

path = HTTP:path_get()

debug("path=%s\n",path)

agent = HTTP:header_get_value("User-Agent")

if agent:lower():find("iphone") or agent:lower():find("ipad") then

debug("found iphone or ipad in User-Agent %s \n", agent)

HTTP:redirect("https://m.mymobilesite.com%s",path)

end

}

Insert random message ID into a header

FortiADC offers the feature to insert messages and message IDs into HTTP request headers.

when HTTP_REQUEST{

ID=HTTP:rand_id()-- a 32-long string of HEX symbols

HTTP:header_insert("Message-ID",ID)

}

General HTTP redirect

You can redirect both HTTP requests and HTTP responses to a given location.

GENERAL_REDIRECT_DEMO:

when HTTP_REQUEST{

--can be used in both HTTP_REQUEST and HTTP_RESPONSE

--code and cookie are optional, code can be 301, 302, 303, 307, 308, if missed, 302 is used

t={}

t["code"] = 302;

t["url"] = "www.example.com"

t["cookie"] = "name=value; Expires=Wed, 09 Jun 2021 10:18:14 GMT"

HTTP:redirect_t(t);

}

Use request headers in other events

You can get stored request headers by using the session ID.

when RULE_INIT{

--initialize the global so-called "environment" variable

env={}

}

when HTTP_REQUEST{

sess_id = HTTP:get_session_id()

req={}

--store whatever you want to req, take url as an example

req["url"] = HTTP_uri_get()

env[id] = req

}

when HTTP_RESPONSE{

sess_id = HTTP:get_session_id()

req = env[id]

--now you can access the stored request headers

debug("my stored request url is %s\n", req["url"]);

}

when HTTP_DATA_REQUEST{

sess_id = HTTP:get_session_id()

req = env[id]

--now you can access the stored request headers

debug("my stored request url is %s\n", req["url"]);

}

when HTTP_DATA_RESPONSE{

sess_id = HTTP:get_session_id()

req = env[id]

--now you can access the stored request headers

debug("my stored request url is %s\n", req["url"]);

}

Compare IP address to address group

You can compare IP addresses to an internal list of IP addresses. The script will return different results signifying whether the IP is in the list.

when RULE_INIT{

--initialize the address group here

--for IPv4 address, mask can be a number between 0 to 32 or a dotted format

--support both IPv4 and IPv6, for IPv6, the mask is a number between 0 and 128

addr_group = "192.168.1.0/24"

addr_group = addr_group..",172.30.1.0/255.255.0.0"

addr_group = addr_group..",::ffff:172.40.1.0/120"

}

when HTTP_REQUEST{

client_ip = HTTP:client_addr()

matched = cmp_addr(client_ip, addr_group)

if matched then

debug("client ip found in address group\n");

else

debug("client ip not in address group\n");

end

}

Redirect HTTP to HTTPS

You can redirect an HTTP request from an HTTP location to an HTTPS location.

when HTTP_REQUEST{

Host = HTTP:header_get_value("host")

Url = HTTP:uri_get()

HTTP:redirect("https://%s%s", Host, Url)

}

Rewrite HTTP to HTTPS in location

You can rewrite HTTP request headers to replace all HTTP addresses with HTTPS addresses in the redirect location.

when HTTP_RESPONSE{

loc = HTTP:header_get_value("Location")

if loc then

newloc = string.gsub(loc, "http", "https") --replace all http by https in the redirect location

HTTP:header_replace("Location", newloc);

end

}

Rewrite HTTP to HTTPS in referer

You can rewrite HTTP request headers to replace all HTTP addresses with HTTPS addresses in the redirect referer.

when HTTP_RESPONSE{

ref = HTTP:header_get_value("Referer")

if ref then

newref = string.gsub(ref, "http", "https") --replace all http by https in the referer header

HTTP:header_replace("Referer", newref);

end

}

Rewrite HTTPS to HTTP in location

You can rewrite HTTP request headers to replace all HTTPS addresses with HTTP addresses in the redirect location.

when HTTP_RESPONSE{

loc = HTTP:header_get_value("Location")

if loc then

newloc = string.gsub(loc, "https", "http") --replace all https by http in the redirect location

HTTP:header_replace("Location", newloc);

end

}

Rewrite HTTPS to HTTP in referer

You can rewrite HTTP request headers to replace all HTTPS addresses with HTTP addresses in the redirect referer.

when HTTP_RESPONSE{

ref = HTTP:header_get_value("Referer")

if ref then

newref = string.gsub(ref, "https", "http") --replace all https by http in the referer header

HTTP:header_replace("Referer", newref);

end

}

Fetch data from HTTP events

You can collect data from both HTTP request and HTTP response events. You can then manipulate this data.

when HTTP_REQUEST{

--HTTP:collect command can be used in both HTTP_REQUEST and HTTP_RESPONSE events

--size is optional, otherwise, it will collect up to the full length or when 1.25M is reached

t={}

t["size"] = 100;

HTTP:collect(t)

}

when HTTP_DATA_REQUEST{

--check the size of the content

t={};

t["operation"]="size";

sz=HTTP:payload(t);

debug("content size: %s\n", sz);

--fetch the collected content

--offset and size are optional

t={};

t["operation"]="content";

t["offset"] = 0;

t["size"] = sz;

ct=HTTP:payload(t);

debug("content: %s\n", ct);

--do your own manipulation on the collected content

--replace the collected content by your new data

--offset and size are optional

t={};

t["operation"]="set";

t["offset"] = 0;

t["size"] = sz;

t["data"]="NEW DATA to SEND";

ret = HTTP:payload(t);

debug("set ret %s\n", ret);

}

Replace HTTP body data

You can find, remove, and replace data in the body of an HTTP request.

when HTTP_REQUEST{

--HTTP:collect command can be used in both HTTP_REQUEST and HTTP_RESPONSE events

--size is optional, otherwise, it will collect up to the full length or when 1.25M is reached

t={}

t["size"] = 100;

HTTP:collect(t)

}

when HTTP_DATA_REQUEST{

--check the size of the content

t={};

t["operation"]="size";

sz=HTTP:payload(t);

debug("content size: %s\n", sz);

--find a string or a regular expression in the buffered data

--offset, size and scope are optional, if scope is missing, "all" is assumed

t={};

t["operation"]="find";

t["offset"] = 0;

t["size"] = sz;

t["scope"] = "all";-- or "first"

t["data"] = "your string or a regular expression to find";

if HTTP:payload(t) then

debug("found %d occurences\n", ret);

else

debug("not found\n");

end

--remove a string or a regular expression in the buffered data

--offset, size and scope are optional, if scope is missing, "all" is assumed

t={};

t["operation"]="remove";

t["offset"] = 0;

t["size"] = sz;

t["scope"] = "all";-- or "first"

t["data"] = "your string or a regular expression to find";

if HTTP:payload(t) then

debug("removed %d occurences\n", ret);

else

debug("not found\n");

end

--replace a string or a regular expression in the buffered data by a new string

--offset, size and scope are optional, if scope is missing, "all" is assumed

t={};

t["operation"]="replace";

t["offset"] = 0;

t["size"] = sz;

t["scope"] = "all";-- or "first"

t["data"] = "your string or a regular expression to find";

t["new_data"] = "your new data";

if HTTP:payload(t) then

debug("replaced %d occurences\n", ret);

else

debug("not found\n");

end

}

Persist

You can set the entry to the persist table and real server will be assigned after lookup

when RULE_INIT {

env={}

PROXY:init_stick_tbl_timeout(1000)

}

when PERSISTENCE {

debug("PERSIST \n");

t={};

t["operation"] = "get_valid_server";

ret_tbl = HTTP: persist(t);

if(ret_tbl) then

for srv, state in pairs(ret_tbl) do

debug("server %s status %s\n", srv, state);

end

end

t={};

t["operation"] = "save_tbl";

t["hash_value"]= "hash_str";

t["srv_name"]= "rsrv_70";

ret = HTTP: persist(t)

if ret then

debug("save table success\n");

else

debug("save table failed\n");

end

t={};

t["operation"] = "dump_tbl";

t["index"] = 0;

t["count"] = 500;

ret_tbl = HTTP: persist(t)

if(ret_tbl) then

for k, cnt in pairs(ret_tbl) do

debug(" hash %s srv_name %s\n", k, cnt)

end

end

t={};

t["hash_value"]= "hash_str";

ret = HTTP:lookup_tbl(t);

if ret then

debug("LOOKUP success\n");

else

debug("LOOKUP fail\n");

end

}

Post_persist

You can get the current assigned server in POST_PERSIT and assign real server you like by setting table and lookup in PERSISTENCE

when RULE_INIT {

env={}

PROXY:init_stick_tbl_timeout(1000)

}

when PERSISTENCE {

debug("PERSIST \n");

t={};

t["hash_value"]= "hash_str";

ret = HTTP:lookup_tbl(t);

if ret then

debug("LOOKUP success\n");

else

debug("LOOKUP fail\n");

end

}

when POST_PERSIST {

debug("POST PERSIST \n");

t={};

t["operation"] = "get_current_assigned_server"

ret_tbl = HTTP: persist(t)

if ret then

debug("assign to %s\n", ret_tbl);

else

debug("get_current_assigned_server failed\n");

end

t={};

t["operation"] = "save_tbl";

t["hash_value"]= "hash_str";

t["srv_name"]= "rsrv_70";

ret = HTTP: persist(t)

if ret then

debug("save table success\n");

else

debug("save table failed\n");

end

}

Run multiple scripts

You can run multiple scripts in FortiADC. When running multiple scripts, you may set a priority number for each script. FortiADC will run them in order from lowest priority to highest priority. The default priority is 500. if two scripts have the same priority number, they will be executed in the order in which they were added.

--script 1:

when HTTP_REQUEST priority 500 {

LB:routing(“cr1”)

}

--script 2:

when HTTP_RESPONSE priority 500 {

HTTP:close()

}

--script 3:

when HTTP_REQUEST priority 400 {

LB:routing(“cr2”)

}

--script 4:

when HTTP_RESPONSE priority 600 {

HTTP:close()

}

Prioritize scripts

While running multiple scripts, you can prioritize scripts. Add a priority number to each script when you create it, and FortiADC will run them in order from lowest priority to highest priority. The default priority is 500.If two scripts have the same priority number, they will be executed in the order in which they were added.

when RULE_INIT priority 14 {

--This is one of the script to demo the control of multiple scripts

--please change the priority of each event according to your need

debug("INIT in script 1\n");

}

when HTTP_REQUEST priority 12 {

debug("HTTP_REQUEST in script 1\n");

--add your own manipulation here

--you can disable rest of the HTTP_REQUEST events from executing by disabling this event

t={};

t["event"]="req"; -- can be "req", "res", "data_req", and "data_res"

t["operation"]="disable"; -- can be "enable", and "disable"

HTTP:set_event(t);

debug("disable rest of the HTTP_REQUEST events in script 1\n");

--you can also disable other events, say HTTP_RESPONSE, DATA events

--in the case of keep-alive, all events will be re-enabled automatically even though they are disabled in previous TRANSACTION using the HTTP:set_event(t) command. To disable this automatic re-enabling behavior, you can call HTTP:set_auto(t) as below

t={};

t["event"]="req"; -- can be "req", "res", "data_req", and "data_res"

t["operation"]="disable"; -- can be "enable", and "disable"

HTTP:set_auto(t);

debug("disable automatic re-enabling of the HTTP_REQUEST events in script 1\n");

--you can also disable automatic re-enabling for other events, say HTTP_RESPONSE, DATA events

}

or

when RULE_INIT priority 24 {

--This is one of the script to demo the control of multiple scripts

--please change the priority of each event according to your need

debug("INIT in script 2\n");

}

when HTTP_REQUEST priority 24 {

debug("HTTP_REQUEST in script 2\n");

--add your own manipulation here

--you can disable rest of the HTTP_REQUEST events from executing by disabling this event

t={};

t["event"]="req"; -- can be "req", "res", "data_req", and "data_res"

t["operation"]="disable"; -- can be "enable", and "disable"

HTTP:set_event(t);

debug("disable rest of the HTTP_REQUEST events in script 2\n");

--you can also disable other events, say HTTP_RESPONSE, DATA events

--in the case of keep-alive, all events will be re-enabled automatically even though they are disabled in previous TRANSACTION using the HTTP:set_event(t) command. To disable this automatic re-enabling behavior, you can call HTTP:set_auto(t) as below

t={};

t["event"]="req"; -- can be "req", "res", "data_req", and "data_res"

t["operation"]="disable"; -- can be "enable", and "disable"

HTTP:set_auto(t);

debug("disable automatic re-enabling of the HTTP_REQUEST events in script 2\n");

--you can also disable automatic re-enabling for other events, say HTTP_RESPONSE, DATA events

}