Cookie Based Routing Inside TrafficServer Using cookie_remap
This remap plugin makes decisions about where to send your request based on properties present (or absent) within the HTTP Cookie header. It can also make decisions based on your uri (url path + query.)
Features
Also supports sub-level cookies
K indicates top-level cookie “K”
K.l indicates top-level cookie “K”, subfield “l”
Cookie exists / Cookie doesn’t exist
Cookie or uri matches string
Cookie or uri matches regex (with match replacement in the sendto like http://foo.com/$1/$2)
Cookie falls into a hash/bucket range
Can url encode dynamic data
Limitations
Does not support Plugin Chaining
Setup
The plugin is specified in remap.config using a syntax similar to:
map http://foo.com http://bar.com @plugin=/usr/bin/trafficserver/libexec64/cookie_remap.so @pparam=/home/trafficserver/conf/cookie_remap/cookie_remap.txt
Operations
All operations are specified in a YAML configuration file you pass as @pparam on the plugin configuration line. YAML is very simple syntax. See the example configuration files below.
Each operation results in a sendto action. That means that, if matched, cookie_remap forwards the request to the given sendto
url. It can be proxied or redirected. An else
sendto can be specified, in which case a failure to match will forward the request also. Once a sendto is invoked:
cookie_remap will not process any more “operations” from the configuration
the default destination specified in the remap.config file will not be used; it will be replaced by the
sendto
Each operation
can have multiple “sub-operations”, connected with an conjunction operator. Currently, only the and
operator is supported. So, you can say, “if cookie exists, and
uri is x
, then redirect.”
cookie: X|X.Y
This sub-operation is testing against the X cookie or X.Y cookie where X.Y denotes the X cookie, sub cookie Y e.g
A=ACOOKIE;B=data&f=fsub&z=zsub;
A will operate on ACOOKIE
B will operate on data&f=fsub&z=zsub
B.f will operate on fsub
target: puri
When the cookie key is omitted, the operation is applied to the request uri instead. If this key and value is specified, the uri for the operation will be the pre-remapped, rather than the remapped, uri.
operation: exists|not exists|string|regex|bucket
This keyword actually denotes a “suboperation” - it can be specified multiple times, connected with and
, and send the user to a given destination.
exists: Test for the existence of a cookie
not exists: Test for the non-existence of a cookie
string: string match
regex: regex matching with $1 - $9 replaced in
sendto
bucket: Hash the cookie and check if it falls in a bucket
The cookie
operator must be specified in the YAML file just before the suboperation that will apply to the cookie.
The string
, regex
and bucket
operate on the specified cookie, or if no cookie is specified, they will operate on the uri of the request.
match: str
Match the cookie data to str. If no cookie is specified, match to the request uri.
regex: str
Sets the regex to str. Matching is enabled with $1-$9 (replaced in sendto). Note that only the final regex match in an operation will be used to populate the substitutions $1-$9. If no cookie is specified, match to the request uri.
bucket|hash: X/Y
Hashes (bucketizes) the data in Y buckets. If you fall into the first X of them, this suboperation passes. If no cookie is specified, match to the request uri.
bucket: 1/100
will effectively bucketize 1% of your users
sendto|url: url
if the sub-operation(s) all match, send to url
status: HTTP status-code
if the sub-operation(s) all match, set the status code (e.g. set it to 302). In the case of a redirect, the sendto URL becomes the redirect URL.
else: url [optional]
If one of the sub-operations fails, send to url. This is optional. If there is no ‘else’, we will continue to process operations until either one succeeds, there is an else in one of the operations or we fall through to the default mapping from remap.config
connector: and
‘and’ is the only supported connector
Reserved path expressions
The following expressions can be used in either the sendto or else
URLs, and will be expanded.
$cr_req_url
Replaced with the full original url.
Therefore, a rule like:
op:
cookie: K
operation: exists
sendto: http://foo.com/?.done=$cr_req_url
and a request that matches, e.g.
http://bar.com/hello?fruit=bananas
will become
http://foo.com/?.done=http://bar.com/hello?fruit=bananas
$cr_urlencode()
Replaced with a urlencoded version of its argument. The url argument is aggressively encoded such that all non-alphanumeric characters are converted to % hex notation. The simple algorithm could probably be refined in the future to be less aggressive (encode fewer characters.)
Therefore, a rule like:
op:
cookie: B
operation: exists
sendto: http://foo.com/?.done=$cr_urlencode($cr_req_url)
and a request that matches, e.g.
http://bar.com/hello?fruit=bananas
will become
http://foo.com/?.done=http%3A%2F%2Fbar%2Ecom@2Fhello%3Ffruit%3Dbananas
$path
$path can be used to replace in either the sendto or else URLs the original request path. Therefore a rule like:
op:
cookie: K
operation: exists
sendto: http://foo.com/$path/x/y/z
and a request like http://finance.yahoo.com/photos/what/ever/ that matches the rule
map http://finance.yahoo.com/photos/ http://newfinance.yahoo.com/1k.html @plugin=cookie_remap.so @pparam=foo.txt
will become http://foo.com/photos/what/ever/x/y/z
$unmatched_path
$unmatched_path can be used to gather the URL arguments beyond what was matched by the remap rule. Therefore a rule like:
op:
cookie: K
operation: exists
sendto: http://foo.com/$unmatched_path/x/y/z
and a request like http://finance.yahoo.com/photos/what/ever/ that matches the rule
map http://finance.yahoo.com/photos/ http://newfinance.yahoo.com/1k.html @plugin=cookie_remap.so @pparam=foo.txt
will become http://foo.com/what/ever/matches/x/y/z
Alternatives using pre-remapped URL
$cr_req_url, $path and $unamatched_path are based on the remapped URL. To use the pre-remapped URL, instead use $cr_req_purl, $ppath and $unmatched_ppath, respectively.
An example configuration file
first match “wins” (top down)
#comments
#are allowed
op:
cookie: K
operation: exists
url: http://www.yahoo.com
op:
cookie: K
operation: exists
connector: and
cookie: K.l
operation: not exists
sendto: http://www.yahoo.com
op:
cookie: Y
operation: bucket
bucket: 1/1000
connector: and
cookie: Y.l
operation: regex
regex: (.*)
connector: and
cookie: Y.n
operation: string
match: foobar
sendto: http://cnn.com/$1
else: http://yahoo.com
Debugging things
The easiest way to debug problems with this plugin is to run in the following manner:
bin/traffic_server -T cookie_remap
which will produce output on startup, and for each request. Be aware that this mode of running trafficserver is extremely inefficient and should only be used for debugging.
Initial output
Initially, you will notice output describing each operation and how trafficserver interpreted the information from your configuration file:
[Jul 8 13:08:34.183] Server {3187168} DIAG: (cookie_remap) loading cookie remap configuration file from /homes/ebalsa/dev/yts_mods/cookie_remap/example_config.txt
[Jul 8 13:08:34.199] Server {3187168} DIAG: (cookie_remap) ++++operation++++
[Jul 8 13:08:34.199] Server {3187168} DIAG: (cookie_remap) sending to: http://finance.yahoo.com/2k.html
[Jul 8 13:08:34.199] Server {3187168} DIAG: (cookie_remap) if these operations match:
[Jul 8 13:08:34.200] Server {3187168} DIAG: (cookie_remap) +++subop+++
[Jul 8 13:08:34.200] Server {3187168} DIAG: (cookie_remap) cookie: B
[Jul 8 13:08:34.200] Server {3187168} DIAG: (cookie_remap) operation: bucket
[Jul 8 13:08:34.200] Server {3187168} DIAG: (cookie_remap) bucket: 1/100
[Jul 8 13:08:34.200] Server {3187168} DIAG: (cookie_remap) taking: 1
[Jul 8 13:08:34.200] Server {3187168} DIAG: (cookie_remap) out of: 100
[Jul 8 13:08:34.200] Server {3187168} DIAG: (cookie_remap) +++subop+++
[Jul 8 13:08:34.201] Server {3187168} DIAG: (cookie_remap) cookie: Y.l
[Jul 8 13:08:34.201] Server {3187168} DIAG: (cookie_remap) operation: exists
[Jul 8 13:08:34.201] Server {3187168} DIAG: (cookie_remap) ++++operation++++
[Jul 8 13:08:34.201] Server {3187168} DIAG: (cookie_remap) sending to: http://X.existed.com
[Jul 8 13:08:34.201] Server {3187168} DIAG: (cookie_remap) if these operations match:
[Jul 8 13:08:34.201] Server {3187168} DIAG: (cookie_remap) +++subop+++
[Jul 8 13:08:34.201] Server {3187168} DIAG: (cookie_remap) cookie: PH.l
[Jul 8 13:08:34.202] Server {3187168} DIAG: (cookie_remap) operation: exists
[Jul 8 13:08:34.202] Server {3187168} DIAG: (cookie_remap) # of ops: 2
each operation is enumerated and is more-or-less human readable from the top-down. From now on, each request has information spit out to the console with debugging information on how the cookie_remap is treating this request.
Comments
Comments are allowed in the configuration file if they begin with ‘#’