Forum Discussion

kc2kth_49679's avatar
kc2kth_49679
Icon for Nimbostratus rankNimbostratus
Feb 06, 2009

Rewrite host and URI, then redirect

 

I thought I was pretty close on this one, but I can't quite get it to work. I need to rewrite a portion of a URI (drop part of the path and change the name of the page), change the host name, then send a redirect back with the new host and uri. It seems I can't use string map to change the path and page name all at once since there is a slash separating the two. I suppose I could use two string maps, but I thought there was probably a better method I'm missing.

 

 

Here's the code I've done so far.

 

 

when HTTP_REQUEST {

 

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

 

"app.domain.com" {

 

 

set host www.google.com

 

HTTP::uri [string map {"index.jsp" "index.asp"} [HTTP::uri]]

 

log local0. "redirecting to $host[HTTP::uri]"

 

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

 

}

 

}

 

}

7 Replies

  • That's a good start. You can do pairs of replacements within string map (Click here😞

    string map {find1 replace1 find2 replace2} [HTTP::uri]

    You don't need the -glob flag on switch if you're not using wildcards in the switch cases. You skip the intermediate variable for $host. And HTTP::uri is cached in the event, so logging it after modifying it won't show the change.

     
     when HTTP_REQUEST {   
        switch [string tolower [HTTP::host]] {   
           "app.domain.com" {   
              log local0. "redirecting to http://www.google.com[string map -nocase {"/path_to_replace" "/new_path" "index.jsp" "index.asp"} [HTTP::uri]]"   
              HTTP::redirect "http://www.google.com[string map -nocase {"/path_to_replace" "/new_path" "index.jsp" "index.asp"} [HTTP::uri]]"   
           }   
        }   
     }   
     

    Aaron
  • Thanks Aaron. I did need to change the redirect again though to get it working. Something closer to my final is below. It looks like the cached URI was being passed in your example instead of what I thought I was updating with the string map. Changing that line a bit allowed me to change the redirect to reference the two variables instead.

     
      when HTTP_REQUEST {  
         switch [string tolower [HTTP::host]] {  
            "app.domain.com" {  
               set host "www.google.com"  
               set uri [string map -nocase {"/path_to_replace" "/new_path" "index.jsp" "index.asp"} [HTTP::uri]]  
               HTTP::redirect http://$host$uri  
            }  
         }  
      }  
     
  • Of course, you're right. Sorry about that. I edited the example above to skip setting the URI with HTTP::uri.

     

     

    Aaron
  • So my requirements have changed a bit. I have the code below working. However what we now need to do is NOT send a redirect to the client and instead rewrite the uri portion of the request and send that to an existing server pool.

     

     

    I'm confused about how to not pass the cached uri and instead pass what I've rewritten to the pool members. The host value should remain unchanged now.

     

     

      
     when HTTP_REQUEST {   
          switch [string tolower [HTTP::host]] {   
             "app.domain.com" {   
                set host "www.google.com" 
                set uri [string map -nocase {"/path_to_replace" "/new_path" "index.jsp" "index.asp"} [HTTP::uri]] 
                HTTP::redirect http://$host$uri 
             }   
          }   
       } 
     

     

     

     

    I tried setting HTTP::uri and then using 'pool pool_name', but the original uri value seems to be passed, not what I've rewritten.
  • Replying to myself here since I did some more work on this, but still don't have it working the way I was hoping. Basically we want to try and avoid a large number of redirects that would occur with our original solution and instead update the uri and select a pool for the connection. Poking around here I found some examples that used HTTP::header replace, but I haven't had much luck.

     

     

    Updating this post since it hit me that what I'm trying to replace is the payload, not a header. I'm looking into using HTTP::payload replace now to rewrite the client request.
  • You're very close. To update the URI without a redirect you can use HTTP::uri. You'd use HTTP::header replace for the Host header because for whatever reason, you cannot rewrite the host using HTTP::host "newhost".

     
     when HTTP_REQUEST {  
        switch [string tolower [HTTP::host]] {  
           "host.domain.com" {  
              HTTP::uri [string map {"/string" "/newstring" "page.jsp" "newpage.aspx"} [HTTP::uri]]  
              pool pool_name  
           } 
           default {  
              reject  
           }  
        } 
     } 
     

    The values for HTTP::uri and HTTP::host are cached within the same rule and event so logging the updated value won't show the change. But it is actually changed in the request sent to the server. If you'd like to verify this, you can add a second HTTP_REQUEST event which runs after the default priority HTTP_REQUEST event:

     
     when HTTP_REQUEST {  
      
        log local0. "Priority 500: [IP::client_addr]:[TCP::client_port]: Original request to [HTTP::host][HTTP::uri]" 
      
        switch [string tolower [HTTP::host]] {  
           "host.domain.com" {  
              HTTP::uri [string map {"/string" "/newstring" "page.jsp" "newpage.aspx"} [HTTP::uri]]  
              pool pool_name  
           } 
           default {  
              reject  
           }  
        } 
     } 
     when HTTP_REQUEST priority 501 { 
        log local0. "Priority 501: [IP::client_addr]:[TCP::client_port]: Updated  request to [HTTP::host][HTTP::uri]" 
     } 
     

    Aaron
  •  

    Brilliant - that did it. And that is much simpler than using HTTP::payload as well I would guess which is the path I was about to start down. I knew from the earlier work the values were cached, but I also thought I wasn't able to change them because they were cached. Thanks for the help, and for the schooling! I'm sure I'll find plenty of uses for the techniques I've learned in this thread.