Forum Discussion

Frank_Ziebarth_'s avatar
Frank_Ziebarth_
Icon for Nimbostratus rankNimbostratus
Jun 16, 2006

rewrite an URI with a request parameter

Hallo

 

 

we have two webservices in the development, so the the uri is change very often.

 

Our end-user should connect to these server to an easy URI

 

http://server/portal/

 

http://server/info/

 

 

 

This is my iRule:

 

 

when HTTP_REQUEST {

 

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

 

HTTP::uri "/version02.webservices.portal/"

 

use pool SDS_Pool01

 

}

 

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

 

HTTP::uri "/version04.webservices.info/"

 

use pool SDS_Pool02

 

}

 

}

 

 

It works for

 

http://server/portal/service.asmx

 

and

 

http://server/portal/test/service.asmx

 

 

but not for

 

http://server/portal/service.asmx?op=SignVerifyCompressEmail

 

In this case it looks like that the iRule cut the part

 

"?op=SignVerifyCompressEmail"

 

 

I can´t understand that, can somebody tell me where my mistake is?

 

10 Replies

  • Hi,

     

     

    I think your mistake may be that you replace the whole URI with a constant (/version04.webservices.info/). Everything in the URI will be replaced by this. Try to insert a log sentence and explore what happens.

     

     

    You can solve this with a regsub command or the like. I don't garante the syntax but I hope you get the idea :-).

     

     

    Example

     

     

    when HTTP_REQUEST {

     

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

     

    log local0. "Original HTTP uri = [HTTP::uri]"

     

    set [HTTP::uri] [regsub -all ^/portal [HTTP::uri] "/version02.webservices.portal"]

     

    log local0. "New HTTP uri = [HTTP::uri]"

     

    use pool SDS_Pool01

     

    }

     

    }
  • HTTP::uri refers to the entire URI, including the query string. So when you are setting the URI with HTTP::uri "/version02.webservices.portal/" or HTTP::uri "/version04.webservices.info/", you are overwriting the entire URI.

     

     

    If you want to replace the instance of /portal/ with /version02.webservices.portal/ and leave the rest of the URI intact, you can use string map:

     

     

    when HTTP_REQUEST {

     

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

     

    HTTP::uri [string map { /portal/ /version02.webservices.portal/ } [HTTP::uri]]

     

    pool SDS_Pool01

     

    }

     

    elseif { [HTTP::uri] starts_with "/info/" } {

     

    HTTP::uri [string map { /info/ /version04.webservices.info/ } [HTTP::uri]]

     

    pool SDS_Pool02

     

    }

     

    }

     

     

    Aaron
  • Oh, I didn't know that. I'll remember it for later use. Actually I've wondered about the performance of regexp/regsub compared to their alternatives.

     

     

    Thanks again.
  • You can evaluate the cpu performance of either method by turning timing on your rules:

    
    timing on
    when CLIENT_ACCEPTED  {
      ...
    }

    or a specific event

    
    when CLIENT_ACCEPTED {
      ...
    }
    when HTTP_REQUEST timing on {
      ...
    }

    This post by unRuleY details how to interpret the cpu data:

    http://devcentral.f5.com/Default.aspx?tabid=28&view=topic&forumid=5&postid=3650

    To evaluate memory performance use tmctl mem:

    
    [root@bigip:Active] uid  tmctl mem
    name          allocs bytes_allocated max_bytes
    ------------- ------ --------------- ---------
    rules              3             280       280
    tcl             1148          111844    186779

  • You can also view the timing statistics (cpu cycles) with the new F5 iRule Editor. Right click on an iRule in the list and select the "Properties" menu item and then select the Statistics tab.

     

     

    -Joe
  • Thanks joe and citizen_elah. Your anwers to this post answers all of my wonderings about iRule performance metering. Great stuff!
  • Hallo,

     

     

    thanks for your fast response.

     

    I use the version from hoolio, it works fine.

     

     

    I would like extend the iRule with logging

     

     

    when HTTP_REQUEST {

     

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

     

    log local0. "Original HTTP uri = [HTTP::uri]"

     

    HTTP::uri [string map { /portal/ /version02.webservices.portal/ } [HTTP::uri]]

     

    log local0. "New HTTP uri = [HTTP::uri]"

     

    pool SDS_Pool01

     

    }

     

    ....

     

     

    But the logging not work correctly, there is no different between the Original URI and the URI after the rewrite.

     

     

    tmm tmm[989]: Rule _TEST_Frank : Original HTTP uri = /portal/default.aspx

     

    tmm tmm[989]: Rule _TEST_Frank : New HTTP uri = / portal/default.aspx

     

     

    Can you help me here again?

     

    Thanks Frank.

     

  • It looks like HTTP::uri only refers to the original client request. Perhaps one of the gurus can explain this.

    I used the following to verify the rewrite though:

    
    when HTTP_REQUEST {
        set debug to 1 to enable logging to /var/log/ltm. Set to 0 to disable logging.
       set debug 1
       if { [HTTP::uri] contains "uri1" } {
          HTTP::uri [string map { uri1 uri2 } [HTTP::uri]]
          if {$debug}{ 
             log local0. "Rewrote URI from: [HTTP::uri]"
             log local0. 'Rewrote URI to:   [string map { uri1 uri2 } [HTTP::uri]]" 
          }
       }
    }
  • I've see this behavior before as well. Maybe unRuleY could comment on why it is but I've verified that the URI is correctly changed with the HTTP::uri command but the contents of the variable isn't correctly updated to match. Maybe this has something to do with variable caching but I'm not sure. If you want to log the values, store it into a temporary variable.

    when HTTP_REQUEST {
    if { [HTTP::uri] starts_with "/portal/" } {
      log local0. "Original HTTP uri = [HTTP::uri]"
      set newUri [string map { /portal/ /version02.webservices.portal/ } [HTTP::uri]] 
      HTTP::uri $newUri
      log local0. "New HTTP uri = $newUri"
      pool SDS_Pool01
    }

    -Joe