Forum Discussion

Keith_90333's avatar
Keith_90333
Icon for Nimbostratus rankNimbostratus
Mar 18, 2016

iRule HTTP::Redirect not working on some URLs (aborting connection)

Hi all,

I'm a bit stumped....

class SharePoint-Redirect_Urls_Old_Path_To_New_Path_DataGroup {
   {
      "/ALL_ENTRIES_MUST_BE" { "LOWER_CASE_TO_MATCH" }
      "/cop/da-apt" { "/co/da-apt" }
      "/cop/hrp-prh" { "/co/hrp-prh" }
      "/cop/knowledge" { "/co/knowledge" }
      "/cop/ypn-rjp" { "/co/ypn-rjp" }
      "/projects-projets" { "/pj" }
      "/governance-gouvernance" { "/gv" }
      "/communities-communautes" { "/co" }
      "/search/" { "/search-recherche/" }
   }
}

rule SharePoint-Redirect_Urls_Old_Path_To_New_Path {
when RULE_INIT {
    Set this option to 1 to log messages (to /var/log/ltm by default)
   set static::log_old_to_new_path_redir 1  
}
when CLIENT_ACCEPTED {
    if {[TCP::local_port] eq 443} {
        set CLIENT_HTTP_TYPE "https"
    } else {
        set CLIENT_HTTP_TYPE "http"
    }

}
when HTTP_REQUEST {
    set MATCH_FOUND [class match [string tolower [HTTP::path]] starts_with SharePoint-Redirect_Urls_Old_Path_To_New_Path_DataGroup]

    if {($static::log_old_to_new_path_redir) && ($MATCH_FOUND)}{
        set CLIENT_ADDR [IP::client_addr]
        set XFF [HTTP::header X-Forwarded-For]
        set ID "[TCP::local_port][expr { int(100000000 * rand()) }]"
         seconds from epoch + random number
        set ID "[TCP::local_port]-[clock seconds]-[expr { int(100000000 * rand()) }]"
        set REQUEST_RECEIVE [clock clicks -milliseconds]
        set HTTP_LPATH [string tolower [HTTP::path]]
    }

    if {$MATCH_FOUND} {
        set KEY [class match -name $HTTP_LPATH starts_with SharePoint-Redirect_Urls_Old_Path_To_New_Path_DataGroup]
        set VAL [class match -value $HTTP_LPATH starts_with SharePoint-Redirect_Urls_Old_Path_To_New_Path_DataGroup]
        set REPLACED_PATH [string map -nocase [list $KEY $VAL] [HTTP::uri]]   
        set REDIRECT_URL "$CLIENT_HTTP_TYPE://[HTTP::host]$REPLACED_PATH"

        if {($static::log_old_to_new_path_redir) && ($MATCH_FOUND)}{
            log local0.info "URI_PATH:[HTTP::path] || KEY:$KEY || VAL:$VAL || REPLACED_PATH:$REPLACED_PATH || REDIRECT_URL:$REDIRECT_URL - SRC:$CLIENT_ADDR  ID:$ID" 
        }

        HTTP::redirect $REDIRECT_URL
    }
}
when HTTP_REQUEST_SEND {
    if {($static::log_old_to_new_path_redir) && ($MATCH_FOUND)}{
        set REQUEST_SEND [clock clicks -milliseconds]
        set REQUEST_WAIT [expr {$REQUEST_SEND - $REQUEST_RECEIVE}]
        log local0. "URI PATH: $HTTP_LPATH  - SRC:$CLIENT_ADDR  ID:$ID"
    }
} 
when HTTP_RESPONSE {
    if {($static::log_old_to_new_path_redir) && ($MATCH_FOUND)}{
        set RESPONSE_TIME [expr {[clock clicks -milliseconds] - $REQUEST_SEND}]
        log local0. "URI PATH: $HTTP_LPATH - HTTP[HTTP::status] $RESPONSE_TIME\ms/$REQUEST_WAIT\ms [LB::server addr] - SRC:$CLIENT_ADDR ID:$ID"
    }
}
}

The lines entries for projects to search in the data group all fail to redirect... I get a browser aborted.

However, the log entries show up as successful....

DOES actually redirect:

Rule SharePoint-Redirect_Urls_Old_Path_To_New_Path : URI_PATH:/cop/ypn-rjp/ || KEY:/cop/ypn-rjp || VAL:/co/ypn-rjp || REPLACED_PATH:/co/ypn-rjp/ || REDIRECT_URL:https://collab.MY_DOMAIN_HERE/co/ypn-rjp/ - SRC:10.128.42.207 ID:1458297076443-20424180

DOES NOT actually redirect (aborted)

Rule SharePoint-Redirect_Urls_Old_Path_To_New_Path : URI_PATH:/communities-communautes/cts-cst/ || KEY:/communities-communautes/cts-cst || VAL:/co/cts-cst || REPLACED_PATH:/co/cts-cst/ || REDIRECT_URL:https://collab.MY_DOMAIN_HERE/co/cts-cst/ - SRC:10.128.42.207 ID:1458297033443-17874026

The events HTTP_REQUEST_SEND and HTTP_RESPONSE never fire (no logging) which makes sense if the redirect is happening in the HTTP_REQUEST. I added them in to ensure that nothing was actually being sent to the back-end servers.

Do any of you have any insight as to why this would happen?

Cheers!

  • Further experiments make me think it is (I know this is bizarre) something to do with getting the strings from the DataGroup... It makes no sense to me at all. I have another iRule that does work:

     

    when RULE_INIT {
         Set this option to 1 to log debug messages (to /var/log/ltm by default)
        set static::debug_managed_path_redirects 0  
    }
    when CLIENT_ACCEPTED {
        if {[TCP::local_port] eq 443} {
            set CLIENT_HTTP_TYPE "https"
        } else {
            set CLIENT_HTTP_TYPE "http"
        }
    
    }
    when HTTP_REQUEST {
        set HTTP_PATH [string tolower [HTTP::path]]
    
        switch -glob $HTTP_PATH {
            "/projects-projets*" -
            "/governance-gouvernance*" -
            "/communities-communautes*" {
                if {$static::debug_managed_path_redirects}{
                    log local0. "Match found in $HTTP_PATH"
                }
                if {$HTTP_PATH starts_with "/projects-projets" } {
                    set LONG_MANAGED_PATH "/projects-projets"
                    set SHORT_MANAGED_PATH "/pj"
                } elseif {$HTTP_PATH starts_with "/governance-gouvernance" } {
                    set LONG_MANAGED_PATH "/governance-gouvernance"
                    set SHORT_MANAGED_PATH "/gv"
                } elseif {$HTTP_PATH starts_with "/communities-communautes" } {
                    set LONG_MANAGED_PATH "/communities-communautes"
                    set SHORT_MANAGED_PATH "/co"
                }
    
                set PATH_LENGTH [string length $LONG_MANAGED_PATH ]
                set REDIRECT_PATH "$SHORT_MANAGED_PATH[string range [HTTP::uri] $PATH_LENGTH end]"
    
                if {$static::debug_managed_path_redirects}{
                    log local0. "REDIRECT_FROM:$HTTP_PATH - REDIRECT_TO:$REDIRECT_PATH"
                }
    
                HTTP::redirect "$CLIENT_HTTP_TYPE://[HTTP::host]$REDIRECT_PATH"
            }
            default {
                 don't do anything...
            }
        }
    }

    The above code redirects correctly.

     

    I then went and created a new Data Group with the following entries:

     

    class SharePoint-Managed_Path_Redirects_DataGroup {
       {
          "/projects-projets" { "/pj" }
          "/governance-gouvernance" { "/gv" }
          "/communities-communautes" { "/co" }
          "/search/" { "/search-recherche/" }
       }
    }

    And modified the code in my original question to use the new data group for matching, but use the string substitution from the working redirect to create the redirect URL:

     

    when HTTP_REQUEST {
        set MATCH_FOUND [class match [string tolower [HTTP::path]] starts_with SharePoint-Managed_Path_Redirects_DataGroup]
    
        if {($static::log_old_to_new_path_redir2) && ($MATCH_FOUND)}{
            set CLIENT_ADDR [IP::client_addr]
             seconds from epoch + random number
            set ID "[TCP::local_port]-[clock seconds]-[expr { int(100000000 * rand()) }]"
            set REQUEST_RECEIVE [clock clicks -milliseconds]
            set HTTP_LPATH [string tolower [HTTP::path]]
        }
    
        if {$MATCH_FOUND} {
            set KEY [class match -name $HTTP_LPATH starts_with SharePoint-Managed_Path_Redirects_DataGroup]
            set VAL [class match -value $HTTP_LPATH starts_with SharePoint-Managed_Path_Redirects_DataGroup]
            set REPLACED_PATH [string map -nocase [list $KEY $VAL] [HTTP::uri]]   
            set REDIRECT_URL "$CLIENT_HTTP_TYPE://[HTTP::host]$REPLACED_PATH"
            set PATH_LENGTH [string length $KEY ]
            set REDIRECT_URL "$VAL[string range [HTTP::uri] $PATH_LENGTH end]"
    
            if {($static::log_old_to_new_path_redir2) && ($MATCH_FOUND)}{
                log local0.info "URI_PATH:[HTTP::path] - KEY:$KEY - VAL:$VAL - REDIRECT_URL:$REDIRECT_URL - SRC:$CLIENT_ADDR  ID:$ID" 
            }
    
            HTTP::redirect $REDIRECT_URL
        }
    }

    And the redirect gets aborted using the above. So strange (to me)....