Forum Discussion

Ivan_38122's avatar
Ivan_38122
Icon for Nimbostratus rankNimbostratus
Apr 24, 2018

Issue with iRule to choose mobile user agent for specific URI and multiple pool selection

Dear friends,

I need to ask for your help because I have break my head since the last week to fix an issue designing an iRule, I have tried several ways but it just works partially. I need to design an iRule that chooses users with mobile devices and load balance their requests to specific application pools matching the URI. For desktop users it must be the same, this must be in the virtual server in this example is . I have designed almost 10 different iRules I have tried in several ways and the iRules which are closer to my target are these:

I designed the first iRule in this way:

when HTTP_REQUEST {

if { [class match [HTTP::header User-Agent] contains "mobile_class"] } {

When I try to access with a mobile device, it doesn't works, it seems it doesn't match with any user agent, then I receive a connection reset, because the options doesn't match with any member of the datagroup mobile_class

switch -glob [HTTP::host] {

"example.com" {

HTTP::redirect "; }

"; {

                if { [HTTP::uri] equals "/" } {
                HTTP::header insert X-Forwarded-For [IP::remote_addr]
                HTTP::redirect "www.example.com/ctsMobilePublic/index.jsp"

                } elseif { [class match [HTTP::uri] starts_with "ctsmobile_class"] } {
                HTTP::header insert X-Forwarded-For [IP::remote_addr]
                pool Pool-CTSM

                } elseif { [class match [HTTP::uri] starts_with "regmobile_class"] } {
                HTTP::header insert X-Forwarded-For [IP::remote_addr]
                pool Pool-CTSN

                }
                                                        }

                                                    }
`


 This else happen when the user agent doesn't belong to the datagroup list, this is for desktop users

} else {

`switch -glob [HTTP::host] {

                            "example.com" {

                                 HTTP::redirect "www.example.com/servlet/example/inicio"
`

 Here in this case, when you write the URL: example.com/ it redirects to [www.example.com/servlet/example/inicio/www.example.com/servlet/example/inicio](//www.example.com/servlet/example/inicio/www.example.com/servlet/example/inicio)

`                                                   }

                            "www.example.com" {
`

 Here in this if, when you write the URL: [www.example.com/](//www.example.com/) it redirects to [www.example.com/servlet/example/inicio/www.example.com/servlet/example/inicio](//www.example.com/servlet/example/inicio/www.example.com/servlet/example/inicio)

`            if { [HTTP::uri] equals "/" } {
                 HTTP::redirect "www.example.com/servlet/example/inicio"

          } elseif { [class match [HTTP::uri] starts_with "SSO_class"] } {
                  HTTP::header insert X-Forwarded-For [IP::remote_addr]
                  pool Pool-SSOSERVICIOS

          } elseif { [class match [HTTP::uri] starts_with "CTSN_class"] } {
                  HTTP::header insert X-Forwarded-For [IP::remote_addr]
                  pool Pool-CTSN
`

 The main page URI /servlet/example/inicio must match with this class SRVLT_class

`          }  elseif { [class match [HTTP::uri] starts_with "SRVLT_class"] } {
                  HTTP::header insert X-Forwarded-For [IP::remote_addr]
              SSL::disable serverside
                  pool Pool-SRVLT

                                            }
                                        }

                                        }
                                } }

I had to cut the iRule because it was very long and I had not enough space here, but, is just long because it has several elseif for each URI that matches with pool. With less cases but the logical is the same, for desktop users now is working fine except when I use the redirects for example.com and , because it makes something like a loop. But where it have become very complex is when I try to separate by mobile devices. By the way, the data group list mobile_class string type contains: ipad, iphone, android, windows phone, windows ce,etc

Can somebody help me please, I would appreciate a lot any suggestion Thanks a lot Ivan

2 Replies

  • Sorry but the first iRule was very long to attach the second wich I will explain now:

    when HTTP_REQUEST {

    switch -glob [string tolower [HTTP::header User-Agent]] { "ipad" - "iphone" - "android" - "windows phone" - "windows ce" - "bada" - "bb10" - "blackberry" - "symbinos" - "symbain os" - "symbian" - "java" - "winowsphone" - "windowsce" {

    This iRule works very similar than the last iRule, but in this case I used a switch with user agent cases, instead the if and the datagroup list I made in the last example, unfortunatelly this also doesn't works, I activated the logging of all if cases for the mobile user agents, but I receive this output: 01220001: ltm1dmz tmm3[21425] TCL error: /Common/iRule_Portal_v9 - can't read "dest_node": no such variable while executing "log "Sending URI:[HTTP::uri] DEST:$dest_node at $node_ip $node_port"" ("; arm line 13) invoked from within "switch -glob [HTTP::host] { "example.com" { HTTP::redirect "; ..." ("android" arm line 3) invoked from within "switch -glob [string tolower [HTTP::header User-Agent]] { "android" - "ipad" - "iphone" - "iPhone" - ..." I can't find why if it matches in the line 3 ANDROID, it doesn't processes the traffic in the switch case, because with this iRule I have the same results of the first iRule with mobile devices, a simple RESET

    switch -glob [HTTP::host] {

                           "example.com" {
    
                    HTTP::redirect "www.example.com/ctsMobilePublic/index.jsp"
    
                                                       }
    
                           "www.example.com" {
    
                    if { [HTTP::uri] equals "/" } {
                    HTTP::header insert X-Forwarded-For [IP::remote_addr]
                    log "Request: [HTTP::uri] from [IP::client_addr]"
                    log "Sending URI:[HTTP::uri] DEST:$dest_node at $node_ip $node_port"
                    log "Request: [HTTP::uri] from [IP::client_addr]"
                     HTTP::redirect "www.example.com/ctsMobilePublic/index.jsp"
    
                    } elseif { [class match [HTTP::uri] starts_with "ctsmobile_class"] } {
                    HTTP::header insert X-Forwarded-For [IP::remote_addr]
                    log "Request: [HTTP::uri] from [IP::client_addr]"
                    log "Sending URI:[HTTP::uri] DEST:$dest_node at $node_ip $node_port"
                    pool Pool-CTSM
    
                    } elseif { [class match [HTTP::uri] starts_with "regmobile_class"] } {
                    HTTP::header insert X-Forwarded-For [IP::remote_addr]
                    log "Request: [HTTP::uri] from [IP::client_addr]"
                    log "Sending URI:[HTTP::uri] DEST:$dest_node at $node_ip $node_port"
                    pool Pool-CTSN
    
                    } elseif { [class match [HTTP::uri] starts_with "regwebv2mob_class"] } {
                    HTTP::header insert X-Forwarded-For [IP::remote_addr]
                    log "Request: [HTTP::uri] from [IP::client_addr]"
                    log "Sending URI:[HTTP::uri] DEST:$dest_node at $node_ip $node_port"
                    pool Pool-CTXPRESSX
    
                    }
                                                            }
    
    
    
    
                                                        }
    
    
    
            default  {
    
    switch -glob [HTTP::host] {
    
    
                                "example.com" {
    
                                     HTTP::redirect "www.example.com/servlet/example/inicio"
    
                                                       }
    
    
                                "www.example.com" {
    
                if { [HTTP::uri] equals "/" } {
                     HTTP::header insert X-Forwarded-For [IP::remote_addr]
                     log "Request: [HTTP::uri] from [IP::client_addr]"
                     log "Sending URI:[HTTP::uri] DEST:$dest_node at $node_ip $node_port"
                     log "Request: [HTTP::uri] from [IP::client_addr]"
                     HTTP::uri /servlet/example/inicio
                     SSL::disable serverside
                     pool Pool-SRVLT
    
    In this iRule, I used the expression HTTP::uri /servlet/example/inicio to rewrite the iRule, but it seems that internally it do the request to the real server with the URI:/servlet/example/inicio but in the browser it keeps the URI / : this makes fail some components of the web page, it only works if the original request is , then it matches with the SRVLT_class and send the request to the Pool-SRVLT, working pretty good.
              } elseif { [class match [HTTP::uri] starts_with "SSO_class"] } {
                      HTTP::header insert X-Forwarded-For [IP::remote_addr]
                      log "Request: [HTTP::uri] from [IP::client_addr]"
                      log "Sending URI:[HTTP::uri] DEST:$dest_node at $node_ip $node_port"
                      pool Pool-SSOSERVICIOS
    
              } elseif { [class match [HTTP::uri] starts_with "Indic_class"] } {
                      HTTP::header insert X-Forwarded-For [IP::remote_addr]
                      log "Request: [HTTP::uri] from [IP::client_addr]"
                      log "Sending URI:[HTTP::uri] DEST:$dest_node at $node_ip $node_port"
                      SSL::disable serverside
                      pool Pool-Indicadores
    
              } elseif { [class match [HTTP::uri] starts_with "WSIND_class"] } {
                      HTTP::header insert X-Forwarded-For [IP::remote_addr]
                      log "Request: [HTTP::uri] from [IP::client_addr]"
                      log "Sending URI:[HTTP::uri] DEST:$dest_node at $node_ip $node_port"
                      pool Pool-WSIND
    
              } elseif { [class match [HTTP::uri] starts_with "CTSN_class"] } {
                      HTTP::header insert X-Forwarded-For [IP::remote_addr]
                      log "Request: [HTTP::uri] from [IP::client_addr]"
                      log "Sending URI:[HTTP::uri] DEST:$dest_node at $node_ip $node_port"
                      pool $fcpool
                      log "Request: [HTTP::uri] from [IP::client_addr]"
                      pool Pool-CTSN
    
              } elseif { [class match [HTTP::uri] starts_with "SRVLT_class"] } {
                      HTTP::header insert X-Forwarded-For [IP::remote_addr]
                      log "Request: [HTTP::uri] from [IP::client_addr]"
                      log "Sending URI:[HTTP::uri] DEST:$dest_node at $node_ip $node_port"
                      SSL::disable serverside
                      pool Pool-SRVLT
              }
    
    
                                                }
    
                                                }
    
                                            }
                                    }
                    }
    

    I would appreciate a lot any answer or help to fix this issue, I have designed more than 10 iRules without success.

    Thanks a lot Ivan

  • Hello,

     

    I think that your irule worked. But you have to now on important thing. If your use an Variable that you not set the irule process stopped and you will receive an reset.

     

    In your case you try to display specific logs with a variable that not set:

     

    TCL error: /Common/iRule_Portal_v9 - can't read "dest_node": no such variable while executing "log "Sending URI:[HTTP::uri] DEST:$dest_node at $node_ip $node_port"" (";; arm line 13) invoked from within "switch -glob [HTTP::host] { "example.com" { HTTP::redirect ";; ..." ("android" arm line 3) invoked from within "switch -glob [string tolower [HTTP::header User-Agent]] { "android" - "ipad" - "iphone" - "iPhone" - ..."

     

    First of remove all varibale that are not set or set all of this. Then try again.

     

    Regards,