Forum Discussion

DeltaRho2K_2167's avatar
DeltaRho2K_2167
Icon for Nimbostratus rankNimbostratus
Feb 15, 2012

iRule Redirect Question/Help

OK, first, let me apologize for my newbieness to iRules. We just got our LTMs a little over a month ago and I have been thrown in - trial by fire - to get this thing working with multiple applications, using SAN certificates, and now - with the use of iRules. That brings me here to seek out iRule help.

 

 

I currently have an iRule in place that checks the incoming http request and if there is no extension and no trailing slash, it adds the trailing slash. The purpose for this is so the IIS on the back-end knows to serve the default document. Without it, the IIS was interpreting the call as a file without an extension, and thus - giving a 404 error. The TrailingSlash_DataList is a data group that contains file extensions called by the web app (.jpg, .png, .html, .js, .jsp, .wsdl, .htm, .aspx, .asmx, .css, etc).

 

 

It looks like this --

 

 

when HTTP_REQUEST {

 

set req [HTTP::path]

 

if { !([matchclass $req ends_with $::TrailingSlash_DataList]) and !($req ends with "/") } {

 

HTTP::redirect https://[HTTP::host][HTTP::uri]/

 

}

 

}

 

 

 

---------------------------------------------------------------

 

 

Now, I have been given a new task which I believe should also involve a redirect, but I am not 100% certain.

 

 

With the above iRule, if someone calls:

 

https://www.mydomain.com

 

Then they are redirected to:

 

https://www.mydomain.com/

 

 

Example 2 - if someone calls:

 

https://www.mydomain.com/virtualdir

 

Then they are redirected to:

 

https://www.mydomain.com/virtualdir/

 

 

 

Now, what I need to happen is when someone calls:

 

https://www.mydomain.com

 

Then they would need to be redirected to:

 

https://www.mydomain.com/virtualdir/

 

 

 

I'm pretty sure this is simple enough -

 

 

I need to have the incoming request first check to see if the URL is only the FQDN (without any additional URI - with or without the slashes) - and if so, then I need it to do the redirect to the virtual directory with the trailing slash appended to it.

 

 

If the http request contains a URI (like the virtual directory already appended), then I just need to make sure it has that trailing slash appended to it.

 

 

I get the logic, and I'm sure it can be done. I'm just not familiar enough with the iRule syntax to put it together. Any help would be appreciated.

 

 

(LTM 1600, version 10.2.3)

 

2 Replies

  • First thing is to remove the $:: prefix from your iRule's reference to the data group(s). This won't work in 10.x+.

     

     

    Also note that the HTTP path will never be null. If a user types in http://example.com into the address bar, the browser appends a default path of /.

     

     

    Next, in order to know which paths to redirect with a trailing slash, you should be able to include them in your existing TrailingSlash_DataList data group.

     

     

    You shouldn't need to check if the path already ends with a trailing slash as your data group entries shouldn't have a trailing slash. So you can remove this 'and !($req ends with "/")'.

     

     

    If things aren't working, add some debug logging of the original path and what you're redirecting to to help troubleshoot.

     

     

    Aaron
  • Thanks Aaron -- I'll reply point by point below:

    First thing is to remove the $:: prefix from your iRule's reference to the data group(s). This won't work in 10.x+. [I need to look at the deprecation list, and what changes need to be made so my iRules don't break later on down the road - but the rule I have written above does work to append trailing slashes to requests and we're on 10.2.3. I've alrady been warned that the 11.x syntax does change, so I will be reviewing all of my iRules and updating accordingly whenever we get around to updating to 11.x. Thanks for the heads up - this is definitely something I'm looking more into because I don't want my stuff to break when we upgrade to 11.x.]

    Also note that the HTTP path will never be null. If a user types in http://example.com into the address bar, the browser appends a default path of /.

    [The check for the trailing slash is due to the fact that the LTM is passing incoming SSL traffic to http traffic on the backend - so that trailing slash doesn't get passed - the end result is the IIS on the backend server thinks it's a file and not a directory - so it tries to pass a file it can't find instead of the default document within the virtual directory - 404]

    Next, in order to know which paths to redirect with a trailing slash, you should be able to include them in your existing TrailingSlash_DataList data group.

    [The TrailingSlash_DataGroup isn't evaluating paths. it's used to compare the path in order to determine if the extension exists or not. Basically because of the situation above, I have to evaluate all incoming traffic to see if it has an extension or a trailing slash.]

    You shouldn't need to check if the path already ends with a trailing slash as your data group entries shouldn't have a trailing slash. So you can remove this 'and !($req ends with "/")'.

    [Again, see above notes]

    If things aren't working, add some debug logging of the original path and what you're redirecting to to help troubleshoot.

    [I'm not sure where to do the debugging, but I used Fiddler 2 to monitor my outbound http/https traffic in order to learn about the need for the trailing slash and write the iRule and DataGroup to support it.]

    Aaron

    Now, as to the original question, I actually got it to work... Here's the iRule I setup to get it working.

    
    when HTTP_REQUEST { 
    
     When the request first comes in, we're going to check to see if it's to the FQDN with nothing appended 
     ie https://ac.fsg.amer.csc.com (this condition results in the uri equaling a "/" only) 
     If the uri is only a slash, then we'll redirect to the virtual directory (ACWeb) 
     IIS interprets this "ACWeb/" entry as a request to a directory and loads the default page. 
    
      if { [HTTP::uri] equals "/" } { 
        HTTP::redirect https://[HTTP::host][HTTP::uri]ACWeb/ 
      } elseif { !([matchclass [HTTP::path] ends_with $::TrailingSlash_DataList]) and !([HTTP::path] ends_with "/") } { 
    
     If, for some reason, a request is made directly to ACWeb or any other virtual directory (without the slash) 
     then we need to make sure the trailing slash is added in a redirection. 
    
        HTTP::redirect https://[HTTP::host][HTTP::uri]/ 
      } 
    }

    Some test results:

    User browses to https://www.mydomain.com - redirected to https://www.mydomain.com/ACWeb/

    User browses to https://www.mydomain.com/ACWeb - redirected to https://www.mydomain.com/ACWeb/

    User browses to https://www.mydomain.com/ACWeb/ - no redirection - traffic passed through http class.

    User browses to https://www.mydomain.com/ACWebServices - redirected to https://www.mydomain.com/ACWebServices/

    User browses to https://www.mydomain.com/ACWeb/Login.aspx - no redirection - traffic passed through http class.

    I'm not sure if this is the best or most efficient way to do this, but it works. If you know of a way this can be done better, I'm all ears.