Forum Discussion

C_D_18583's avatar
C_D_18583
Icon for Nimbostratus rankNimbostratus
Nov 03, 2005

String Manipulation

I have the following piece of code in my iRule

 

elseif { $uri starts_with "/nexus/" } {

 

pool pool1 }

 

elseif { $uri starts_with "/earth/" } {

 

pool pool2}

 

elseif { [string index [HTTP::uri] end] ne "/" } {

 

HTTP::redirect "http://[HTTP::host][HTTP::uri]/"

 

}

 

else {

 

pool pool3

 

}

 

}

 

The string extract is added just incase the user forgets to adds a / after the servlet context. The problem I have with this is that when the following request is received

 

http://testdomain.com/add.html

 

 

What happens is a / is appended as http://testdomain.com/add.html/ and then redirected to pool 3 which causes a 404.

 

 

1) How do I rewrite the rule so that when http://testdomain.com/add.html is received I can by pass the string/redirect statement?

 

2) If the servlet context does not match any above, the request should be directed to pool3 ?

 

 

 

6 Replies

  • You could do a "ends_with" comparison before your check for the slash. if you know the valid extensions that you don't want appended with slashes this should work.

    While you are at it you could use the ends_with in place of your string index command as well.

    elseif { $uri starts_with "/nexus/" } {
      pool pool1
    } elseif { $uri starts_with "/earth/" } {
      pool pool2
    } elseif { [HTTP::uri] ends_with ".html" } {
      pool pool3
    } elseif { not ([HTTP::uri] ends_with "/") } {
      HTTP::redirect "http://[HTTP::host][HTTP::uri]/"
    } else {
      pool pool3
    }

    Is this what you are going for? If not, if you could provide a clear set of inputs and expected results, it will be easier for us to figure out a solution.

    -Joe
  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    A more generic approach may be to simply check the basename for a period and only add the slash if one was not found and it doesn't end with one:

    ...
    if { not ([URI::basename $uri] contains ".") and not ($uri ends_with "/") } {
       HTTP::redirect "http://[HTTP::host][HTTP::uri]/"
    } ...
  • ...if { not ([URI::basename $uri] contains ".") and not ($uri ends_with "/") } { HTTP::redirect "http://[HTTP::host][HTTP::uri]/"} ...

     

    Thanks , the above statement is very close

     

     

    The basename is picking the last item of the uri after the last /

     

     

    For example If I have this case.

     

     

    http://testdomain.com/ADforms/trial

     

     

    Basename picks up trial . I need to extract the first value after the domain which is ADforms . If it does not contain a "." or it does not end with a / then do the HTTP redirect, else go to the next statement.

     

     

     

     

  • getfield should get you where you want to go. You can use getfield to extract a specified field from a string. Using a slash as a delimiter and selecting field 2 you can get the first value after the slash in the URI.

    This will get you the token without the slashes. You can check for the existence of a "." at that point but you won't be able to see if it ended with a slash. I'd suggest for that check you rescan the URI for the extracted token with a slash appended to it.

    So, something like this should work:

    Extract first element after slash in URI
    set f [getfield [HTTP::uri] "/" 2]
     Check if field contains doesn't contain a dot
     and if the uri doesn't contain the field followed by a slash
    if { not ($f contains ".") 
         and not ([HTTP::uri] contains "${f}/") } {
       Perform redirect.
      HTTP::redirect "http://[HTTP::host]/${f}/"
    }

    You could possibly use HTTP::uri in the redirect with a slash appended. That should produce the same result.

    *Standard disclaimer: this iRule hasn't been tested...

    -Joe
  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    I don't know if any of this will help, but...

     

     

    BTW, we also have a command: URI::path

     

    This command has the following forms:

     

     

    URI::path - returns the complete path excluding the basename.

     

    URI::path - return the portion of the path starting after .

     

    URI::path - return the portion of the path specified.

     

    URI::path depth - return the number of directory levels in the path.

     

     

     

    I'd also like to highlight another command that doesn't seem to get much airtime:

     

    URI::compare

     

     

    This command compares two uris without regard to case or encoding.

     

    Unfortunately it doesn't yet support starts_with, ends_with or contains.