iRule: modifying the uri without a redirect

In this case the user wants to change the uri of a HTTP request without forcing a redirect from the client.

We have a unique situation where a client-based DLL is uploading a file to our website. For reasons beyound my control I need to change the destination url without a redirect. When I use a redirect the payload (file to upload) is lost because the DLL is not smart enough to resubmit file for upload.

This can be done with the HTTP::uri command fairly easily. The fun starts with how you go about doing it.

Let's say you want to replace the entire URI with something new. For this example, let's say we need to replace "/foo" with "/bar". This can be done by the following:

when HTTP_REQUEST {
   if { [HTTP::uri] equals "/foo" } {
      HTTP::uri "/bar"
   }
}

But, what happens if you are working with a URI containing get parameters? This way you only know the beginning of the uri. Again, no problem. In this example the following iRule will replace any uri starting with "/foo" with "/bar"

when HTTP_REQUEST {
   if { [HTTP::uri] starts_with "/foo" } {
      HTTP::uri "/bar[string range $uri 4 end]"
   }
}

-Joe

Published Jul 27, 2005
Version 1.0
  • It should work as is. The HTTP::uri command takes two forms, if enclosed in braces with no arguments, it returns the URI. If it is passed a parameter then it uses the passed in variable as the new URI.

     

     

    In the second example, the line

     

     

    HTTP::uri "/bar[string range $uri 4 end]"

     

     

    is a URI assignment with the new value being "/bar" concatenated with the 5th character on in the URI.

     

     

    -Joe
  • There are two ways to modify the URI.

     

     

    1) HTTP redirects. This will send a redirect HTTP response to the client with the Location response header containing the new location. The browser will update the address bar with the new location and issue a new request.

     

     

    2) Transparent header modifications. You can modify the HTTP::uri and HTTP::host values in an iRule without a redirect to the browser. This will make it appear to the server that a different request was made and the browser will not update it's address bar (since a redirect command wasn't made. So, if you want http://www.foo.com/file1.txt to "look like" http://www.bar.com/file2.txt, you can do so with the following iRules code

     

     

    when HTTP_REQUEST {

     

    if { ([HTTP::host] eq "www.foo.com") && ([HTTP::uri] eq "/file1.txt" } {

     

    HTTP::host "www.bar.com"

     

    HTTP::uri "/file2.txt"

     

    }

     

    }

     

     

    Hope this helps...

     

     

    Feel free to post more questions over on the iRules forum if they come up.

     

     

    -Joe
  • Doh, I always forget that HTTP::host doesn't have a write method. This should do it for you.

     

     

    when HTTP_REQUEST {

     

    if { ([HTTP::host] eq "www.foo.com") && ([HTTP::uri] eq "/file1.txt" } {

     

    HTTP::header replace "Host" "www.bar.com"

     

    HTTP::uri "/file2.txt"

     

    }

     

    }

     

     

    -Joe
  • Here you go:

     

     

    when HTTP_REQUEST {

     

    if { [HTTP::uri] starts_with "/support" } {

     

    HTTP::redirect "http://newhost/newuri.ext"

     

    }

     

    }

     

     

    -Joe
  • Jessy, when you said you started it, what did that mean. did you get the error when saving the iRule or was that error put in the log when a request was made through the Virtual Server using that iRule? I don't see anything wrong with your iRule as it's written to cause that error. Especially since I don't see the token "alumno" anywhere outside of the middle of the URL in the redirect statement.

     

     

    -Joe
  • Hi,

     

    Tried the uri change but it doesn't do anything. I'm trying to change the http://abc.com/csm/?.Project=client1 to http://abc.com/web/web.dll?.Project=client1

     

    This is the irule:

     

    when HTTP_REQUEST {

     

    if { [HTTP::uri] starts_with "/csm/" } {

     

    HTTP::uri "/web/web.dll[string range $uri 5 end]"

     

    }

     

    }

     

     

    Do you know what's wrong ?

     

    Thanks, Adrian

     

     

  • DenisGrimard_34's avatar
    DenisGrimard_34
    Historic F5 Account
    I needed to do it like so to catch it properly:

     

     

    when HTTP_REQUEST {

     

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

     

    set newuri "/signon.html"

     

    log "Incoming uri - [HTTP::uri] being translated to $newuri"

     

    HTTP::uri $newuri

     

    }

     

    }

     

     

    If I didnt put in the second part of the if it wouldnt catch it if the user didnt put in the / in Chrome.
  • I'm not sure how this is supposed to work, but it doesn't seem to actually modify the [HTTP::uri] variable as in this example:

     

     

    when HTTP_REQUEST {

     

    if { [string toupper [HTTP::query]] contains "TRIGGER" } {

     

    if { not ([HTTP::uri] starts_with "/new/dir") } {

     

    HTTP::uri /new/dir[HTTP::uri]

     

    }

     

    HTTP::uri [HTTP::uri]&key=secret

     

    HTTP::redirect http://localhost[HTTP::uri]

     

    }

     

    }

     

     

    In the above example, I would expect a request for /?TRIGGER to return a redirect to http://localhost/new/dir/?TRIGGER&key=secret but instead, it returns a redirect for /?TRIGGER, clearly not modifying the [HTTP::uri] at all.