Forum Discussion

Joe_Pipitone's avatar
Joe_Pipitone
Icon for Nimbostratus rankNimbostratus
Jun 08, 2011

Rewriting only part of the URI

I have a request to rewrite only a certain part of our URI, while still passing the last part of the URI. I need to be able to catch all requests and rewrite just part of the URI.

 

 

I have a script already in use that does something similar, but saves the leading digits based on a specific length of the filename. In this case, all articles have a different number of characters, therefore I cannot use that rule.

 

 

 

I'd be thankful if anyone could point me in the right direction. Here's an example:

 

 

 

 

 

 

 

FROM:

 

 

 

http://ourdomain.com/newsletters/Directory2/*

 

 

 

TO:

 

 

 

http://ourdomain.com/newsletters/Directory3/*

 

 

 

 

 

 

 

The asterisk implies that we need to take the name of the article and pass it along as well, while simply rewriting Directory2 to Directory3:

 

 

 

 

 

FROM:

 

 

 

http://ourdomain.com/newsletters/Directory2/some-article.aspx

 

 

 

TO:

 

 

 

http://ourdomain.com/newsletters/Directory3/some-article.aspx

 

 

 

 

 

 

Perhaps I am thinking way too hard about this. I need to try and preserve everything EXCEPT for the directory after /newsletters/. I can't just pass:

 

 

 

http://ourdomain.com/newsletters/Directory3/[HTTP::uri]

 

 

 

as this would duplicate part of the URI making it look like this:

 

 

 

http://ourdomain.com/newsletters/Directory2/newsletters/Directory3/some-article.aspx

 

 

 

So that's why I'm a bit confused....Do I need to perform some sort of scanning using the URI basename, or simply rewrite based on the URI::path?

 

 

 

 

 

 

 

I appreciate any help!

 

 

 

 

 

 

 

 

 

9 Replies

  • I think I've got it - I simply used a string map, and incorporated HTTP::redirect vs HTTP::path as to perform the rewrite / redirect.

     

     

    when HTTP_REQUEST {

     

     

     

    Check if path starts with /newsletters/Directory2

     

    if {[HTTP::path] starts_with "/newsletters/Directory2"}{

     

     

    Replace /newsletters/Directory2 with /newsletters/Directory3 in the path

     

    HTTP::redirect [string map {/newsletters/Directory2 /newsletters/Directory3} [HTTP::path]]

     

    }

     

    }

     

     

     

     

     

  • So with something static like /newsletters/ beginning your URI, you could do a string range (in tlcsh):

    
    set x "/newsletters/Directory2/something/else/entirely/file.txt"
    puts "/newsletters/Directory3[string range $x [string first / $x 13] end]"
    
    /newsletters/Directory3/something/else/entirely/file.txt
    
  • so in iRules, that would be

    
    HTTP::uri "/newsletters/Directory3[string range $x [string first / $x 13] end]"
    

    might need tweaking if not as static as you presented in the request, but gets you along the way...
  • For some reason, when I start adding on string tolower, I keep getting redirect loops. I want to be sure I catch any case in the browser and set it to lowercase - any idea what I may be missing here?

    when HTTP_REQUEST { 
      
       Check if path starts with /newsletters/directory2 
        if { [string tolower [HTTP::path]] starts_with "/newsletters/directory2"}{ 
      
            Replace /newsletters/directory2 with /newsletters/directory3 in the path 
           HTTP::redirect [string map {/newsletters/directory2 /newsletters/directory3} [HTTP::path]] 
        }
     } 
  • OK - I think I got it again - unless someone sees a problem with this performance wise:

    when HTTP_REQUEST { 
      
       Check if path starts with /newsletters/directory2 
        if { [string tolower [HTTP::path]] starts_with "/newsletters/directory2"}{ 
      
            Replace /newsletters/directory2 with /newsletters/directory3 in the path 
           HTTP::redirect [string map {/newsletters/directory2 /newsletters/directory3} [string tolower [HTTP::path]] ] 
        }
     }
  • Hi Joe,

     

     

    Jason's example using string range is more exact and possibly slightly more efficient. But if the string map is working for you it should be fine.

     

     

    Aaron
  • Hmm....will his example work if the length of the entire path varies? When I saw the [string first / $x 13], I was under the impression that it would only replace X number of characters...

     

     

    Here's a few example paths:

     

     

    http://ourdomain.com/newsletters/directory3/2011/04/20110420.aspx

     

     

    and

     

     

    http://ourdomain.com/newsletters/directory3/2011/04/20/asomewhat-long-pathforthe-file-tryingtoreach.aspx

     

     

    As always, your help is greatly appreciated. The string map is working great for me so far, the F5's are still sleeping....
  • so what the string range is doing is taking all the content immediately after /newsletters/directory2. The string first is finding the appropriate start index for the string range by looking for the first "/" in HTTP::uri AFTER the first 13 characters. So this could be /newsletters/ or anything else that was 13 characters long. If it was going to be dynamic in length, then you would want to utilize URI::path and string length as part of the equation, then you wouldn't need to specify newsletter/directory2 at all. Fun stuff!