Forum Discussion

Jay_Henriques_1's avatar
Jay_Henriques_1
Icon for Nimbostratus rankNimbostratus
Dec 07, 2011

b load returning parsing error

Line 20591 is this iRule but I can't find why it is the parsing is failing:

 

 

Velvet Rope Statistics

 

This irule monitor the current number of sessions within a velvet rope'd site. It performs an ajax call

 

to read the session table and compare that against the _manually_ set limit.

 

Not the most elegant solution, but effective. Apply this to a virtual server (not your main VS) and use

 

http://_vs-domain_/vrstatsDDE for statistics. (sub in your domain)

 

 

when RULE_INIT {

 

set static::site-identDDE "ddewcsp"

 

}

 

 

when HTTP_REQUEST {

 

set subtableName "sessionLimit-${static::site-identDDE}"

 

set sessionCount [table keys -subtable $subtableName -count]

 

See if we're on the ajax request

 

if { [HTTP::uri] equals "/updatedSessionCountDDE" } {

 

HTTP::respond 200 content $sessionCount Cache-Control No-Cache Pragma No-Cache

 

} elseif { [HTTP::uri] contains "/vrstatsdde" } {

 

set responseContent "DDE Stats"

 

append responseContent ""

 

append responseContent "body { font-family: Sans-Serif; }"

 

append responseContent "p.headline { font-size:16pt; color: black; }"

 

append responseContent "p.subtitle { font-size:8pt; color: grey; }"

 

append responseContent "p.legend { font-size:8pt; color: white; }"

 

append responseContent "p { font-size:11pt; color: black; }"

 

append responseContent ""

 

append responseContent ""

 

append responseContent "var xmlHttp = null;"

 

append responseContent "function ajaxGetSessionCount() {"

 

append responseContent " var ss = document.getElementById('siteStatus');"

 

append responseContent " ss.innerHTML = 'Updating...';"

 

append responseContent " loadXmlHttp();"

 

append responseContent " sendRequest('/updatedSessionCountDDE');"

 

append responseContent "}"

 

append responseContent "function loadXmlHttp() {"

 

append responseContent " if (window.XMLHttpRequest) {"

 

append responseContent " xmlHttp = new XMLHttpRequest();"

 

append responseContent " } else if (window.ActiveXObject) {"

 

append responseContent " try {"

 

append responseContent " xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');"

 

append responseContent " } catch(e) {}"

 

append responseContent " }"

 

append responseContent "}"

 

append responseContent "function sendRequest(url) {"

 

append responseContent " if (xmlHttp) {"

 

append responseContent " xmlHttp.open('GET', url, true);"

 

append responseContent " xmlHttp.onreadystatechange = onCallback;"

 

append responseContent " xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');"

 

append responseContent " xmlHttp.send(null);"

 

append responseContent " }"

 

append responseContent "}"

 

append responseContent "function onCallback() {"

 

append responseContent " if (xmlHttp.readyState == 4) {"

 

append responseContent " if (xmlHttp.status == 200) {"

 

append responseContent " var result = xmlHttp.responseText;"

 

append responseContent " updateBar(result);" append responseContent " } else {" append responseContent " alert('Error: ' + xmlHttp.status);"

 

append responseContent " }"

 

append responseContent " }"

 

append responseContent "}"

 

append responseContent "function updateBar(ajaxSessionCount) {"

 

append responseContent " var gbb = document.getElementById('guestBarBackground');" append responseContent " var gcb = document.getElementById('guestCounterBar');" append responseContent " var csc = document.getElementById('currentSessionCount');" append responseContent " var ss = document.getElementById('siteStatus');"

 

append responseContent " if (ajaxSessionCount) {"

 

append responseContent " sessionCount = ajaxSessionCount;"

 

append responseContent " } else {"

 

append responseContent " sessionCount = ${sessionCount};"

 

append responseContent " }"

 

append responseContent " csc.innerHTML = 'Current count: ' + sessionCount + '';" append responseContent " var pct_full = sessionCount / ${static::climitDDE};"

 

append responseContent " var gcbWidth = (parseInt(gbb.style.width) * pct_full);" append responseContent " gcb.style.width = gcbWidth;"

 

append responseContent " if (gcbWidth == 0) {"

 

append responseContent " gcb.innerHTML = 'Empty';"

 

append responseContent " } else {"

 

append responseContent " gcb.innerHTML = '' + sessionCount + '';"

 

append responseContent " }"

 

append responseContent " if (pct_full >= 100) {"

 

append responseContent " ss.innerHTML = 'Site at Full Capacity: ' + Math.round((pct_full*100)*1000)/1000 + '%';"

 

append responseContent " } else {"

 

append responseContent " ss.innerHTML = 'Site at Capacity: ' + Math.round((pct_full*100)*1000)/1000 + '%';"

 

append responseContent " }"

 

append responseContent "}"

 

append responseContent ""

 

append responseContent ""

 

append responseContent "Velvet Rule - Current Store Statistics"

 

append responseContent "Instance: ${static::site-identDDE}"

 

append responseContent "Current limit: ${static::climitDDE}"

 

append responseContent ""

 

append responseContent ""

 

append responseContent ""

 

append responseContent ""

 

append responseContent ""

 

append responseContent ""

 

append responseContent "Legend:"

 

append responseContent "Used Slots"

 

append responseContent "Available Slots"

 

append responseContent "subtable name: ${subtableName} "

 

HTTP::respond 200 content $responseContent Cache-Control No-Cache Pragma No-Cache }

 

}
  • Which LTM version are you seeing this on?

     

     

    Also you could make the iRule more efficient by setting the response content in RULE_INIT. You'd need to escape any commands or variables with backslashes (like \${static::site-identDDE}, \${static::climitDDE} and \${subtableName}) and then use subst to evaluate them in HTTP_REQUEST.

     

     

    Here's an example of the concept:

     

    http://devcentral.f5.com/Community/GroupDetails/tabid/1082223/asg/50/aft/30096/showtab/groupforums/Default.aspx30098

     

     

    Aaron
  • We are seeing this on v10.1.0. I will pass along your suggestion and earlier post to the irule author regarding moving the response to the Rule_Init to make the irule more efficient.
  • Can you try testing this to make sure it loads and functions properly?

    
    
     Velvet Rope Statistics 
     This irule monitor the current number of sessions within a velvet rope'd site. It performs an ajax call
     to read the session table and compare that against the _manually_ set limit.
     Not the most elegant solution, but effective. Apply this to a virtual server (not your main VS) and use
     http://_vs-domain_/vrstatsDDE for statistics. (sub in your domain)
    
    when RULE_INIT {
    set static::site-identDDE "ddewcsp"
    set static::responseContent {
    
    DDE Stats
    body { font-family: Sans-Serif; }
    p.headline { font-size:16pt; color: black; }
    p.subtitle { font-size:8pt; color: grey; }
    p.legend { font-size:8pt; color: white; }
    p { font-size:11pt; color: black; }
    var xmlHttp = null;
    function ajaxGetSessionCount() {
     var ss = document.getElementById('siteStatus');
     ss.innerHTML = 'Updating...';
     loadXmlHttp();
     sendRequest('/updatedSessionCountDDE');
    }
    function loadXmlHttp() {
     if (window.XMLHttpRequest) {
     xmlHttp = new XMLHttpRequest();
     } else if (window.ActiveXObject) {
     try {
     xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
     } catch(e) {}
     }
    }
    function sendRequest(url) {
     if (xmlHttp) {
     xmlHttp.open('GET', url, true);
     xmlHttp.onreadystatechange = onCallback;
     xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
     xmlHttp.send(null);
     }
    }
    function onCallback() {
     if (xmlHttp.readyState == 4) {
     if (xmlHttp.status == 200) {
     var result = xmlHttp.responseText;
     updateBar(result);" 
     } else {
     alert('Error: ' + xmlHttp.status);
     }
     }
    }
    function updateBar(ajaxSessionCount) {
     var gbb = document.getElementById('guestBarBackground');" 
     var gcb = document.getElementById('guestCounterBar');" 
     var csc = document.getElementById('currentSessionCount');" 
     var ss = document.getElementById('siteStatus');
     if (ajaxSessionCount) {
     sessionCount = ajaxSessionCount;
     } else {
     sessionCount = \${sessionCount};
     }
     csc.innerHTML = 'Current count: ' + sessionCount + '';" 
     var pct_full = sessionCount / \${static::climitDDE};
     var gcbWidth = (parseInt(gbb.style.width) * pct_full);" 
     gcb.style.width = gcbWidth;
     if (gcbWidth == 0) {
     gcb.innerHTML = 'Empty';
     } else {
     gcb.innerHTML = '' + sessionCount + '';
     }
     if (pct_full >= 100) {
     ss.innerHTML = 'Site at Full Capacity: ' + Math.round((pct_full*100)*1000)/1000 + '%';
     } else {
     ss.innerHTML = 'Site at Capacity: ' + Math.round((pct_full*100)*1000)/1000 + '%';
     }
    }
    Velvet Rule - Current Store Statistics
    Instance: \${static::site-identDDE}
    Current limit: \${static::climitDDE}
    Legend:
    Used Slots
    Available Slots
    subtable name: \${subtableName}
    }
    }
    
    when HTTP_REQUEST {
    set subtableName "sessionLimit-${static::site-identDDE}"
    set sessionCount [table keys -subtable $subtableName -count]
     See if we're on the ajax request
    if { [HTTP::uri] equals "/updatedSessionCountDDE" } {
    HTTP::respond 200 content $sessionCount Cache-Control No-Cache Pragma No-Cache
    } elseif { [HTTP::uri] contains "/vrstatsdde" } {
    HTTP::respond 200 content [subst $static::responseContent] Cache-Control No-Cache Pragma No-Cache
    }
    }
    

    Aaron
  • Thanks Aaron, that did the trick! Do you know why this was breaking config sync? Of course the SysEng/Dev team that wrote the irule had 4 others that were modeled after that one and had to be updated too.
  • Welll, that fixed the config sync issue but now the HTML code doesn't render. Looks like I'll have to work with the SE/Dev to get that worked out.
  • When I navigate to the site's /vrstatsdde, the variables do not get evaluated so the output is \${static::site-identDDE and \${subtableName}. Any ideas as to why the variables are not being evaluated?
  • can you try?

    [root@ve1023:Active] config  b virtual bar list
    virtual bar {
       destination 172.28.19.79:80
       ip protocol 6
       rules myrule
       profiles {
          http {}
          tcp {}
       }
    }
    [root@ve1023:Active] config  b rule myrule list
    rule myrule {
       when RULE_INIT {
            set static::site-identDDE "ddewcsp"
            set static::responseContent {
                    \${static::site-identDDE}
            }
    }
    
    when HTTP_REQUEST {
            HTTP::respond 200 content [subst $static::responseContent]
    }
    }
    
    [root@ve1023:Active] config  curl -i http://172.28.19.79
    HTTP/1.0 200 OK
    Server: BigIP
    Connection: Keep-Alive
    Content-Length: 29
    
    
                    ${static::site-identDDE}
    
    
    [root@ve1023:Active] config  b rule myrule list
    rule myrule {
       when RULE_INIT {
            set static::site-identDDE "ddewcsp"
            set static::responseContent \
                    \${static::site-identDDE}
    }
    
    when HTTP_REQUEST {
            HTTP::respond 200 content [subst $static::responseContent]
    }
    }
    
    [root@ve1023:Active] config  curl -i http://172.28.19.79
    HTTP/1.0 200 OK
    Server: BigIP
    Connection: Keep-Alive
    Content-Length: 7
    
    ddewcsp
    [root@ve1023:Active] config 
    
  • You could use subst twice to get the variable values and not have to escape characters in the static content:

    
    when RULE_INIT {
    set static::responseContent [subst {
    unescaped text
    "hi"
    {text}
    \${static::site-identDDE}
    }]
    }
    
    when HTTP_REQUEST {
    set static::site-identDDE "ddewcsp"
    HTTP::respond 200 content [subst $static::responseContent]
    }
    

    < Connection: Keep-Alive

    < Content-Length: 45

    unescaped text

    "hi"

    {text}

    ddewcsp

    Aaron