Forum Discussion

ppphatak_127926's avatar
ppphatak_127926
Icon for Nimbostratus rankNimbostratus
Sep 07, 2005

findclass function doesnt work

I have a class called "myclass" having two members.

 

www.test1.com,www.yahoo.com

 

www.test2.com,www.msn.com

 

 

and wish to run this single rule against it.

 

 

redirect to getfield(findclass(domain(http_host, 1), myclass), ',', 2)

 

 

Idea is it will check the incoming url, and based on that it will pick up 2nd value after comma from the class and then redirect to it. Meaning, if I access using www.test2.com, then it should redirect me to www.msn.com. This doesnt work. Can someone throw light on what could be wrong pl?

 

Thx.

 

  • Here are the docs for those methods:

    domain() - Parses and returns up to the specified number of trailing parts of a domain name from the specified expression.

    findclass() - The findclass() function finds the member of a class that starts with or matches the beginning of that class member. This function returns the value of that class member. This is similar to the one of class identifier, except that the member is not required to be equal; instead, the member is only required to start with the string and returns the entire member value.

    getfield() - The getfield() function splits a string on a character, and returns the string corresponding to the specific field. The function returns an empty string if the value of does not evaluate into a string, or if the specified value is greater than the number of fields the evaluated was split into. If the specified character or string is not found in the evaluated , then it is treated as one field.

    Let's break this down

    x = domain(http_host,1)
    y = findclass(x, myclass)
    z = getfield(y, ',', 2)

    So, let's say you are passing in the following uri: http://www.test1.com.

    x = domain("www.test1.com", 1)
    // x will now contain "com" since you specified 
    // to return up to 1 trailing part of the domain name.

    I don't think this is what you were going for. I believe that since you have the full domain name in the class, you don't need to be extracting the domain from the full host value.

    I would try the following:

    
    class myclass {
      www.test1.com,www.yahoo.com
      www.test2.com,www.msn.com
    }
    redirect to getfield(findclass(http_host, myclass), ',', 2)

    Or, you if you want to redirect all domain level requests, you could do the following:

    class myclass {
      test1.com,www.yahoo.com
      test2.com,www.msn.com
    }
    redirect to getfield(findclass(domain(http_host, 2), myclass), ',', 2)

    Also, you might want to append the http_uri to the request if you want the uri portion of the redirect to match, otherwise the uri on the original request will be ignored.

    -Joe
  • I tried

     

    redirect to getfield(findclass(http_host, myclass), ',', 2)

     

    but it didnt work. It doesnt get redirected for some reason.

     

  • Martin_Machacek's avatar
    Martin_Machacek
    Historic F5 Account
    Yeah ... I see the problem. There appears to be a bug in the rule evaluator. The findclass function actually matches a class member if it is a substring of the string to match. An example:

    
    class animals {
        "bee"
        "beaver"
    }
    findclass("beer", animals) returns "bee"
    findclass("be", animals) returns empty string
    findclass("bumblebee", animals) returns "bee"
    findclass("beaverbee", animals) returns "bee"

    This bug prevents your solution from working.
  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    I'm not sure that's the problem here since that would actually result in a redirect to the wrong place, not the lack of a redirect at all...
  • Martin_Machacek's avatar
    Martin_Machacek
    Historic F5 Account
    Correct, and it actually works that way in my tests. I'm using following config:

    
    class hostmap {
        "test1.mm.lab,fernet.mm.lab"
        "test2.mm.lab,gin.mm.lab"
        "test3.mm.lab,rum.mm.lab"
    }
    rule mapper {
       redirect to "http://" + getfield(findclass(http_host, hostmap), ',', 2) +  http_uri
    }
    virtual 10.66.66.162:80 unit 1 {
        use rule mapper
    }

    Sending following request to the VIP:

    
    GET /host.html HTTP/1.1
    Host: test1.mm.lab

    yields following response:

    
    HTTP/1.0 302 Found
    Location: http:///host.html
    Connection: close

    If I access the VIP with Firefox I get an Alert saying "www.host.html cannot be found, please check the URL and try again" and a blank window. This is what I expect because the URL in the Location header is really invalid.
  • Sorry. Got it !

     

    How come it is working for you? Can you do me a favor and do exactly what I am doing as mentioned in my original thread on this problem, and see if it works for you pl?
  • Martin_Machacek's avatar
    Martin_Machacek
    Historic F5 Account
    I've already tested configuration almost identical to the one you've posted in the first message in this thread. Results were similar. The only difference was the Location header in the 302 response looked like this:

     

     

    Location: http://

     

     

    and Firefox did not display the alert, just a blank page.
  • Sorry, but honestly I am confused now.

     

    So do you mean it works for you in IE and not in Firefox? OR it works on both? Or it fails?
  • Martin_Machacek's avatar
    Martin_Machacek
    Historic F5 Account
    I've not tested with IE. As a matter of fact, the browser is irrelevant. All that matters is that BIG-IP actually generates a response. The response is useless because of invalid Location, which is caused by findclass working slightly differently than as documented. So, with "work" I mean that BIG-IP generates the redirect response. I've assumed that your problem was that the redirect (302) response has not been generated at all.

    The solution (i.e., redirect based on matching a class member and parsing out the redirect target) cannot work because findclass will never match a class member that is longer than the string to match (as I've explained and demonstrated earlier).

    The only way how to achieve what you want (if I understand your goal correctly) is to use a chain of if-else statements like this:

    
    rule redir-map {
       if(http_host == "www.test1.com") {
           redirect to "http://www.yahoo.com"
       } 
       else if(http_host == "www.test2.com") {
           redirect to "http://www.msn.com"
       }

    The smart solution using findclass is unfortunately not going to work.