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 }

 

}
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    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.
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    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 
    
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    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