RSR Parser
RSR Parser extracts and transforms data from events. Used throughout CGRateS for field mapping, filtering, and data conversion.
A single rule has three parts:
Path - where to get the data
Search/Replace - optional regex transformation
Converters - optional type/format conversion
Single rule syntax:
~path
~path:s/search/replace/
~path{*converter}
~path:s/search/replace/{*converter1&*converter2}
Multiple rules can be chained with ; - their outputs are concatenated:
~*req.Account;~*req.Destination
With Account=``1001`` and Destination=``+111``, this produces 1001+111.
Paths
Dynamic paths start with ~ and use a prefix to specify the data source, some examples:
Prefix |
Source |
|---|---|
|
Request/event fields |
|
Reply fields |
|
Session variables |
|
Options values |
|
CGRateS request |
|
CGRateS reply |
Static values without the ~ prefix are used as literal text.
Nested paths use dot notation:
~*req.Service-Information.SMS-Information.Recipient-Address
Indexed access for array fields:
~*req.Filters[0]
Search & Replace
Regex transformations use :s/pattern/replacement/ syntax. Chain multiple:
~*req.Destination:s/^\+33/0/:s/^0033/0/
Converts prefixes: +33123 or 0033123 becomes 0123.
Use ${1}, ${2} etc. for capture groups:
~*req.Phone:s/^\+(\d{2})(\d+)$/($1) $2/
Converts +441234567 to (44) 1234567.
Dynamic Rules
Parts of a rule can be built at runtime using <> delimiters. The content inside is evaluated first:
THD_ACNT_<~*req.Account>
Account with value 1001 produces rule THD_ACNT_1001.
Escaping
When a value contains ; and you don’t want it split into multiple rules, wrap it in backticks:
constant;`>;q=0.7;expires=3600`;~*req.Account
This parses as three rules: values, >;q=0.7;expires=3600 (literal), and ~*req.Account.
Converters
Converters transform the extracted value. Chain them with &:
~*req.Usage{*duration_seconds&*round:2}
Duration
*duration_seconds- to seconds (float64)*duration_nanoseconds- to nanoseconds (int64)*duration_minutes- to minutes (float64)*duration- parse as Go duration*durfmt:layout- format as time (default:15:04:05)
Math
*round:decimals- round to N decimal places using*middlerounding*round:decimals:method- round with method:*middle,*up, or*down*multiply:value- multiply by value*divide:value- divide by value
String
*strip:side:char- trim all occurrences of char; sides:*prefix,*suffix,*both*strip:side:char:count- trim up to count occurrences*len- string/slice length*slice- parse as slice*json- marshal to JSON
Phone/Network
*libphonenumber:country- format phone as NATIONAL (format 2)*libphonenumber:country:format- format phone; formats: 0=E164, 1=INTERNATIONAL, 2=NATIONAL, 3=RFC3966*e164- extract E.164 from NAPTR record*e164Domain- extract domain from NAPTR record*ip2hex- IP to hex*sipuri_host,*sipuri_user,*sipuri_method- parse SIP URIs*3gpp_uli- decode 3GPP-User-Location-Info hex to ULI object (JSON)*3gpp_uli:path- extract specific field from ULI
Paths: TAI, ECGI, NCGI, etc. return the component as JSON. Fields: TAI.MCC, TAI.TAC, ECGI.ECI. Append .Name for lookup: TAI.MCC.Name (country), TAI.MNC.Name (operator).
Example:
~*req.3GPP-User-Location-Info{*3gpp_uli:TAI.MCC}
~*req.3GPP-User-Location-Info{*3gpp_uli:TAI.MCC.Name}
Time
*unixtime- parse to Unix timestamp*timestring- format time usingLocaltimezone and2006-01-02 15:04:05layout*timestring:tz- format with timezone (e.g.,*timestring:UTC)*timestring:tz:layout- format with timezone and custom layout
Type
*float64- parse as float64*string2hex- string to hex*urldecode- URL decode*urlencode- URL encode
Other
*random- random int*random:min- random int >= min*random:min:max- random int in range*conn_status- UP=1, DOWN=-1*gigawords- gigawords to octets (multiply by 2^32)
Examples
Build an email from account and domain:
~*req.Account;~*req.Domain
Round cost at 2 decimal value:
~*req.Cost{*round:2:*up}
Extract user from SIP URI and format as E.164:
~*req.From{*sipuri_user&*libphonenumber:US:0}
Convert AnswerTime to Go time format:
~*req.AnswerTime{*timestring::2006-01-02 15:04:05.999999999 -0700 MST}