Forum Discussion

Tom_K_185554's avatar
Tom_K_185554
Icon for Nimbostratus rankNimbostratus
Dec 28, 2017

Need to parse the [HTTP::uri] and modify it for a redirect

Hello - I found a really useful irule from Joe Pruitt for parsing the uri

 `when HTTP_REQUEST {
         log local0. "‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐"
         log local0. "URI Information"
         log local0. "‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐"
         log local0. "HTTP::uri: [HTTP::uri]"
         log local0. "‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐"
         log local0. "Path Information"
         log local0. "‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐"
         log local0. "HTTP::path: [HTTP::path]"
         set depth [URI::path [HTTP::uri] depth]
       for {set i 1} {$i <= $depth} {incr i} {
        set dir [URI::path [HTTP::uri] $i $i]
        log local0. "dir\[$i\]: $dir"
   }
   log local0. "Basename: [URI::basename [HTTP::uri]]"
    log local0. "‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐"
    log local0. "Query Information"
    log local0. "‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐"
    log local0. "HTTP::query: [HTTP::query]"
    set namevals [split [HTTP::query] "&"]
    for {set i 0} {$i < [llength $namevals]} {incr i} {
    set params [split [lindex $namevals $i] "="]
    set pnum [expr $i+1]
   log local0. "Param\[$pnum\]: [lindex $params 0]"
     log local0. "Value\[$pnum\]: [lindex $params 1]"
    log local0. "Value\[$pnum\]: [URI::query [HTTP::uri] [lindex $params 0]]"
   }
 }`

The following is the output from running this IRULE.

Dec 27 16:26:09 slot1/oit-lbw-ltmmgd info tmm[12383]: Rule /IDM/log_URI : HTTP::uri: /~geverest/home/data-modeling-course/course-flyer
Dec 27 16:26:09 slot1/oit-lbw-ltmmgd info tmm[12383]: Rule /IDM/log_URI : Path Information
Dec 27 16:26:09 slot1/oit-lbw-ltmmgd info tmm[12383]: Rule /IDM/log_URI : HTTP::path: /~geverest/home/data-modeling-course/course-flyer
Dec 27 16:26:09 slot1/oit-lbw-ltmmgd info tmm[12383]: Rule /IDM/log_URI : dir[1]: /~geverest/
Dec 27 16:26:09 slot1/oit-lbw-ltmmgd info tmm[12383]: Rule /IDM/log_URI : dir[2]: /home/
Dec 27 16:26:09 slot1/oit-lbw-ltmmgd info tmm[12383]: Rule /IDM/log_URI : dir[3]: /data-modeling-course/
Dec 27 16:26:09 slot1/oit-lbw-ltmmgd info tmm[12383]: Rule /IDM/log_URI : Basename: course-flyer
Dec 27 16:26:09 slot1/oit-lbw-ltmmgd info tmm[12383]: Rule /IDM/log_URI : Query Information
Dec 27 16:26:09 slot1/oit-lbw-ltmmgd info tmm[12383]: Rule /IDM/log_URI : &8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;&8208;
Dec 27 16:26:09 slot1/oit-lbw-ltmmgd info tmm[12383]: Rule /IDM/log_URI : HTTP::query:
Dec 27 16:26:09 slot1/oit-lbw-ltmmgd info tmm[12383]: Rule /IDM/log_http_header : =============================================

the path = HTTP::path: /~geverest/home/data-modeling-course/course-flyer the uri = HTTP::uri: /~geverest/home/data-modeling-course/course-flyer /IDM/log_URI : dir[1]: /~geverest/

What I need help with is I need to rebuild the uri to be /home/data-modeling-course/course-flyer (that's just this one example)" from what it was to not have the dir[1] as part of the uri.

All of the uri's have varying depths of directories but "/~something" is always first after the host name and I just need to do the redirect without it.

I have a couple hundred old apache redirects that are in this similar format that are being moved to the f5 as just a virtual server with an IRULE and no pool that just does redirects.

Here is a snippet of the irule

 `when HTTP_REQUEST {
   Check the requested path with wildcard matching
  switch -glob [HTTP::uri] {
  "/~geverest*" 
  {
  set uri [HTTP::uri]
  set path [HTTP::path]
  HTTP::redirect "http://xxxxx.com${uri}"
  event disable all
  }`
  • could you please explain what exactly the code is doing especially the regular expression part and the string map ?

     

    /~ is literal chars (i.e. it matches /~)

     

    %[^/] matches every chars but not / and the matching string will be stored in variable specified later (e.g. it matches geverest and geverest will be stored in first variable)

     

    [scan [HTTP::uri] {/~%[^/]} first] returns number of matching string. so, we can use it to determine whether it is uri we are interested (i.e. 1).

     

    [string map "/~$first/ /" [HTTP::uri]] replace /~$first/ with / in uri (e.g. it replaces /~geverest/ with /).

     

    [root@bip1a:Active:In Sync] config  tclsh
    % set uri "/~geverest/home/data-modeling-course/course-flyer"
    /~geverest/home/data-modeling-course/course-flyer
    
    % scan $uri {/~%[^/]} first
    1
    
    % put $first
    geverest
    
    % string map "/~$first/ /" $uri
    /home/data-modeling-course/course-flyer
  • may this be usable?

    e.g.

    // config
    
    [root@ve13a:Active:In Sync] config  tmsh list ltm virtual bar
    ltm virtual bar {
        destination 172.28.24.10:80
        ip-protocol tcp
        mask 255.255.255.255
        profiles {
            http { }
            tcp { }
        }
        rules {
            qux
        }
        source 0.0.0.0/0
        translate-address enabled
        translate-port enabled
        vs-index 4
    }
    [root@ve13a:Active:In Sync] config  tmsh list ltm rule qux
    ltm rule qux {
    when HTTP_REQUEST {
      if { [scan [HTTP::uri] {/~%[^/]} first] } {
        HTTP::respond 301 noserver Location "http://[HTTP::host][string map "/~$first/ /" [HTTP::uri]]"
      }
    }
    }
    
    // test
    
    [root@ve13a:Active:In Sync] config  curl -I http://172.28.24.10/~geverest/home/data-modeling-course/course-flyer
    HTTP/1.0 301 Moved Permanently
    Location: http://172.28.24.10/home/data-modeling-course/course-flyer
    Connection: Keep-Alive
    Content-Length: 0
    
    [root@ve13a:Active:In Sync] config  curl -I http://172.28.24.10/~helloworld/home/data-modeling-course/course-flyer
    HTTP/1.0 301 Moved Permanently
    Location: http://172.28.24.10/home/data-modeling-course/course-flyer
    Connection: Keep-Alive
    Content-Length: 0
    
    
    • Tom_K_185554's avatar
      Tom_K_185554
      Icon for Nimbostratus rankNimbostratus

      Thank you, This is awesome - does exactly what I need. I am not that great with irules at this level - could you please explain what exactly the code is doing especially the regular expression part and the string map ?

       

       `when HTTP_REQUEST {
           if { [scan [HTTP::uri] {/~%[^/]} first] } {
           HTTP::respond 301 noserver Location "http://[HTTP::host][string map "/~$first/ /" 
             [HTTP::uri]]"
            }
           }`
  • may this be usable?

    e.g.

    // config
    
    [root@ve13a:Active:In Sync] config  tmsh list ltm virtual bar
    ltm virtual bar {
        destination 172.28.24.10:80
        ip-protocol tcp
        mask 255.255.255.255
        profiles {
            http { }
            tcp { }
        }
        rules {
            qux
        }
        source 0.0.0.0/0
        translate-address enabled
        translate-port enabled
        vs-index 4
    }
    [root@ve13a:Active:In Sync] config  tmsh list ltm rule qux
    ltm rule qux {
    when HTTP_REQUEST {
      if { [scan [HTTP::uri] {/~%[^/]} first] } {
        HTTP::respond 301 noserver Location "http://[HTTP::host][string map "/~$first/ /" [HTTP::uri]]"
      }
    }
    }
    
    // test
    
    [root@ve13a:Active:In Sync] config  curl -I http://172.28.24.10/~geverest/home/data-modeling-course/course-flyer
    HTTP/1.0 301 Moved Permanently
    Location: http://172.28.24.10/home/data-modeling-course/course-flyer
    Connection: Keep-Alive
    Content-Length: 0
    
    [root@ve13a:Active:In Sync] config  curl -I http://172.28.24.10/~helloworld/home/data-modeling-course/course-flyer
    HTTP/1.0 301 Moved Permanently
    Location: http://172.28.24.10/home/data-modeling-course/course-flyer
    Connection: Keep-Alive
    Content-Length: 0
    
    
    • Tom_K_185554's avatar
      Tom_K_185554
      Icon for Nimbostratus rankNimbostratus

      Thank you, This is awesome - does exactly what I need. I am not that great with irules at this level - could you please explain what exactly the code is doing especially the regular expression part and the string map ?

       

       `when HTTP_REQUEST {
           if { [scan [HTTP::uri] {/~%[^/]} first] } {
           HTTP::respond 301 noserver Location "http://[HTTP::host][string map "/~$first/ /" 
             [HTTP::uri]]"
            }
           }`
  • could you please explain what exactly the code is doing especially the regular expression part and the string map ?

     

    /~ is literal chars (i.e. it matches /~)

     

    %[^/] matches every chars but not / and the matching string will be stored in variable specified later (e.g. it matches geverest and geverest will be stored in first variable)

     

    [scan [HTTP::uri] {/~%[^/]} first] returns number of matching string. so, we can use it to determine whether it is uri we are interested (i.e. 1).

     

    [string map "/~$first/ /" [HTTP::uri]] replace /~$first/ with / in uri (e.g. it replaces /~geverest/ with /).

     

    [root@bip1a:Active:In Sync] config  tclsh
    % set uri "/~geverest/home/data-modeling-course/course-flyer"
    /~geverest/home/data-modeling-course/course-flyer
    
    % scan $uri {/~%[^/]} first
    1
    
    % put $first
    geverest
    
    % string map "/~$first/ /" $uri
    /home/data-modeling-course/course-flyer
  • could you please explain what exactly the code is doing especially the regular expression part and the string map ?

     

    /~ is literal chars (i.e. it matches /~)

     

    %[^/] matches every chars but not / and the matching string will be stored in variable specified later (e.g. it matches geverest and geverest will be stored in first variable)

     

    [scan [HTTP::uri] {/~%[^/]} first] returns number of matching string. so, we can use it to determine whether it is uri we are interested (i.e. 1).

     

    [string map "/~$first/ /" [HTTP::uri]] replace /~$first/ with / in uri (e.g. it replaces /~geverest/ with /).

     

    [root@bip1a:Active:In Sync] config  tclsh
    % set uri "/~geverest/home/data-modeling-course/course-flyer"
    /~geverest/home/data-modeling-course/course-flyer
    
    % scan $uri {/~%[^/]} first
    1
    
    % put $first
    geverest
    
    % string map "/~$first/ /" $uri
    /home/data-modeling-course/course-flyer