Forum Discussion

Moe_Jartin's avatar
Jan 05, 2009

Context Root Masking/URL Rewrite and pool selection

I have an existing iRule that simply selects poolA based on a list of URIs, everything else goes to poolB.

 

 

when HTTP_REQUEST {

 

switch -glob [string tolower [HTTP::uri]] {

 

/contextroot* -

 

/front* -

 

/static* -

 

/css* -

 

/flash* -

 

/images* -

 

/jsimages* -

 

/xml* -

 

/xsl* -

 

/vgn-ext-templating* -

 

/ -

 

/script/\* -

 

/interpret* -

 

/disabilit* -

 

/shared* {

 

pool pool_A

 

}

 

default {

 

pool pool_B

 

}

 

}

 

}

 

 

 

I have now been tasked with masking the "contextroot" so that the browser does not see it but it is still passed to the server. i.e. browser sends request to www.mysite.org/blah/blah/... and I rewrite to /contextroot/blah/blah/... There are several different variables that "blah" could be but, it IS a defined list. So i am thinking of using a stream profile with a class list. here is a first shot at just the context root masking piece, i'll add the rest of the existing rule later.

 

 

set OriginalURI HTTP::uri

 

 

when HTTP_REQUEST {

 

if {[matchclass [[string tolower [HTTP::uri]] starts_with $::maskedURIs]} { << STREAM::expression "@$OriginalURI@/contextroot/$OriginalURI@" <<<< Can I use the variable inside the stream expression??

 

STREAM::enable

 

pool poolA

 

}

 

}

 

 

when HTTP_RESPONSE {

 

if {[[HTTP::status] == 200] and [[HTTP::header value "Content-Type"] contains text]} {

 

STREAM::expression "@/contextroot@@"

 

STREAM::enable

 

}

 

}

 

 

 

Anyone see anything worng with this or know a better way to do it???

 

 

4 Replies

  • You should only need to change the path in the request. You can do this with HTTP::path instead of a stream filter (which would modify the request payload):

     
      Prepend /contextroot to the original path 
     HTTP::path "/contextroot[HTTP::path]" 
     

    For the response, are you sure non-200 responses won't ever contain the /contextroot? You should also explicitly disable the stream filter if the condition(s) aren't met:

     
     when HTTP_RESPONSE { 
        if {[[HTTP::status] == 200] and [[HTTP::header value "Content-Type"] contains text]} { 
           STREAM::expression "@/contextroot@@" 
           STREAM::enable 
        } else { 
            Disable the stream filter 
           STREAM::disable 
        } 
     } 
     

    Also, you can use variables in a stream expression as long as you wrap the expression with double quotes (like you did) instead of curly braces.

    Aaron
  • Aaron,

     

     

    Thanks for the response. So this is what I have, tying in the original rule:

     

     

    when HTTP_REQUEST {

     

    Prepend /contextroot to masked URIs and send to poolA

     

    if {[matchclass [[string tolower [HTTP::uri]] starts_with $::maskedURIs]} {

     

    HTTP::path "/contextroot[HTTP::path]"

     

    pool poolA

     

    Send other URIs thru original "switch -glob"

     

    } else {[switch -glob [string tolower [HTTP::uri]]} {

     

    /contextroot* -

     

    /front* -

     

    /static* -

     

    /css* -

     

    /flash* -

     

    /images* -

     

    /jsimages* -

     

    /xml* -

     

    /xsl* -

     

    /vgn-ext-templating* -

     

    / -

     

    /script/\* -

     

    /interpret* -

     

    /disabilit* -

     

    /shared* {

     

    pool pool_A

     

    }

     

    default {

     

    pool pool_B

     

    }

     

    }

     

     

    when HTTP_RESPONSE {

     

    Remove /contextroot from HTTP responses

     

    if {[[HTTP::header value "Content-Type"] contains text]} {

     

    STREAM::expression "@/contextroot@@"

     

    STREAM::enable

     

    } else {

     

    STREAM::disable

     

    }

     

    }

     

     

    I removed the 200 response requirement. I had origianlly added it so as not to overwrite 301 or 302 redirects that might happen to have that in it but I guess I should be overwriting those anyway.

     

     

    I will run this on my test box and see if it works. Thanks Again!!!

     

     

    Joe

     

  • OK so new requirement... On the HTTP_RESPONSE I need to only remove the /contextroot for the masked URIs. I initially thought to try:

     

     

    if {[matchclass [[string tolower [HTTP::uri]] starts_with $::maskedURIs] and [[HTTP::header value "Content-Type"] contains text]}

     

    STREAM::expression "@/contextroot$::maskedURIs@@"

     

    STREAM::enable

     

     

    but then I realized that HTTP::uri would only catch the headers and NOT the body, if it worked at all. It there a way to search the HTML response for /contextroot/$::maskedURIs and then remove just the /contextroot ???
  • Once you add an HTTP profile to a VIP, a stream profile will only operate against the HTTP payload (not the HTTP headers). The response doesn't contain a URI exactly. A 30x redirect could contain a URL with the contextroot. You could use 'HTTP::header replace Location $new_value' to do this. Here is an example (Click here).

    How many masked URI's are there? You could possibly read the masked URIs from the class and build a stream expression for each one, but I could see it being resource intensive if there are more than a few. Here is a quick example:

      
      when RULE_INIT {  
        
          The prefix to remove  
         set ::uri_prefix "/contextroot"  
        
          A fake datagroup (actually a list) to test with  
         set ::masked_uris [list /uri1 /uri2 /uri3 /uri4]  
        
          Initialize a variable to test with.  
          This would be used to set the stream expression: STREAM::expression $stream_expression  
         set stream_expression ""  
        
          Loop through each element in the "datagroup"  
         foreach uri $::masked_uris {  
        
             Log the current element  
            log local0. "\$uri: $uri"  
        
             Append the current URI to the stream expression  
            set stream_expression "$stream_expression @$::uri_prefix$uri@$uri@"  
        
             Log the current stream expression  
            log local0. "\$stream_expression: $stream_expression"  
         }  
        
          Log the final result for the stream expression  
         log local0. "\$stream_expression: $stream_expression"  
      }  
      

    And the log output:

    Rule : $uri: /uri1

    Rule : $stream_expression: @/contextroot/uri1@/uri1@

    Rule : $uri: /uri2

    Rule : $stream_expression: @/contextroot/uri1@/uri1@ @/contextroot/uri2@/uri2@

    Rule : $uri: /uri3

    Rule : $stream_expression: @/contextroot/uri1@/uri1@ @/contextroot/uri2@/uri2@ @/contextroot/uri3@/uri3@

    Rule : $uri: /uri4

    Rule : $stream_expression: @/contextroot/uri1@/uri1@ @/contextroot/uri2@/uri2@ @/contextroot/uri3@/uri3@ @/contextroot/uri4@/uri4@

    Rule : $stream_expression: @/contextroot/uri1@/uri1@ @/contextroot/uri2@/uri2@ @/contextroot/uri3@/uri3@ @/contextroot/uri4@/uri4@

    Aaron