Forum Discussion

Rory_Hewitt_F5_'s avatar
May 01, 2015

How can I remove a query parameter from a URL?

I'm trying to remove a query parameter from a URL, and I'm stuck...

 

Basically, I may have 0-n parameters appended to a querystring. They will all have a similar name, starting with "Context_", e.g. "Context_Site", "Context_Device_Type", "Context_Platform". My original plan was to remove the parameters using the following code (which I got from another question on this forum that I can no longer find.:

 

when HTTP_REQUEST {
    if {[HTTP::query] contains "Context_"} {
            set newq ""
             Split query string into separate parameters
            foreach param [split HTTP::query] "&"] {
                     Only add non-context query parms into newq
                    if {!($param starts with "Context_")} {
                            if {$newq eq ""} {
                                    append newq "?$param"
                            } else {
                                    append newq "&$param"
                            }
                    }
                     Add new query portion to path
                    if {$newq ne ""} {
                            HTTP::uri "[HTTP::path]$newq"
                    } else {
                            HTTP::uri [HTTP::path]
                    }
            }
      }
}

The thing is, when I try to run this in Tcl for Windows (Tcl 8.5.8, Tk 8.5.8), I get an "invalid bareword" error for the "contains" in the second line:

 

invalid bareword "contains"
in expression "[HTTP::query] _@_contains "Context_...";
should be "$contains" or "{contains}" or "contains(...)" or ...

I think the syntax is correct, so is this due to a problem with the version of Tcl I'm using?

 

Also, on a related note (and I can ask this as a separate question if it makes sense), if I know that the Context_ parameter(s) will be the last parameter(s) in the URL, is there a better/faster way to remove them than to parse out the querystring into its individual parameters and check each one in turn? For instance, could I just search for the first instance of "&Context_"in HTTP::query and just strip out everything from that point on (also checking for HTTP:query starts with "Context_", I guess).

 

  • kunjan's avatar
    kunjan
    Icon for Nimbostratus rankNimbostratus

    if I know that the Context_ parameter(s) will be the last parameter(s)

    Try this

    when HTTP_REQUEST { 
       if {[HTTP::query] contains "Context_"} {
          set pos [string first "Context_" [HTTP::query]]
          set newq [string range [HTTP::query] 0 [expr $pos -2]]
          HTTP::uri "[HTTP::path]?$newq"
       }
    }
    
  • shouldn't HTTP::uri be after foreach loop?

    by the way, have you tried it on bigip? it seems okay here.

     configuration
    
    [root@ve11c:Active:In Sync] config  tmsh list ltm rule qux
    ltm rule qux {
        when HTTP_REQUEST {
      log local0. "---"
      log local0. "before: [HTTP::uri]"
      if {[HTTP::query] contains "Context_"} {
        set newq ""
        foreach param [split [HTTP::query] "&"] {
          if { !($param starts_with "Context_") } {
            if { $newq eq "" } {
              append newq "?$param"
            } else {
              append newq "&$param"
            }
          }
        }
        if {$newq ne ""} {
          HTTP::uri "[HTTP::path]$newq"
        } else {
          HTTP::uri [HTTP::path]
        }
      }
    }
    when HTTP_REQUEST priority 1000 {
      log local0. "after: [HTTP::uri]"
    }
    }
    
     /var/log/ltm
    
    [root@ve11c:Active:In Sync] config  tail -f /var/log/ltm
    May  2 22:15:28 ve11c info tmm[5649]: Rule /Common/qux : ---
    May  2 22:15:28 ve11c info tmm[5649]: Rule /Common/qux : before: /test
    May  2 22:15:28 ve11c info tmm[5649]: Rule /Common/qux : after: /test
    May  2 22:15:33 ve11c info tmm1[5649]: Rule /Common/qux : ---
    May  2 22:15:33 ve11c info tmm1[5649]: Rule /Common/qux : before: /test?param1=value1
    May  2 22:15:33 ve11c info tmm1[5649]: Rule /Common/qux : after: /test?param1=value1
    May  2 22:15:40 ve11c info tmm[5649]: Rule /Common/qux : ---
    May  2 22:15:40 ve11c info tmm[5649]: Rule /Common/qux : before: /test?param1=value1&Context_1=123
    May  2 22:15:40 ve11c info tmm[5649]: Rule /Common/qux : after: /test?param1=value1
    May  2 22:15:45 ve11c info tmm1[5649]: Rule /Common/qux : ---
    May  2 22:15:45 ve11c info tmm1[5649]: Rule /Common/qux : before: /test?Context_1=123&param1=value1
    May  2 22:15:45 ve11c info tmm1[5649]: Rule /Common/qux : after: /test?param1=value1
    May  2 22:15:50 ve11c info tmm[5649]: Rule /Common/qux : ---
    May  2 22:15:50 ve11c info tmm[5649]: Rule /Common/qux : before: /test?Context_1=123&param1=value1&Context_2=456&param2=value2
    May  2 22:15:50 ve11c info tmm[5649]: Rule /Common/qux : after: /test?param1=value1&param2=value2
    
    • Hey @nitass, thanks for checking that. I suspect it could be just a Tclkit problem then...
  • shouldn't HTTP::uri be after foreach loop?

    by the way, have you tried it on bigip? it seems okay here.

     configuration
    
    [root@ve11c:Active:In Sync] config  tmsh list ltm rule qux
    ltm rule qux {
        when HTTP_REQUEST {
      log local0. "---"
      log local0. "before: [HTTP::uri]"
      if {[HTTP::query] contains "Context_"} {
        set newq ""
        foreach param [split [HTTP::query] "&"] {
          if { !($param starts_with "Context_") } {
            if { $newq eq "" } {
              append newq "?$param"
            } else {
              append newq "&$param"
            }
          }
        }
        if {$newq ne ""} {
          HTTP::uri "[HTTP::path]$newq"
        } else {
          HTTP::uri [HTTP::path]
        }
      }
    }
    when HTTP_REQUEST priority 1000 {
      log local0. "after: [HTTP::uri]"
    }
    }
    
     /var/log/ltm
    
    [root@ve11c:Active:In Sync] config  tail -f /var/log/ltm
    May  2 22:15:28 ve11c info tmm[5649]: Rule /Common/qux : ---
    May  2 22:15:28 ve11c info tmm[5649]: Rule /Common/qux : before: /test
    May  2 22:15:28 ve11c info tmm[5649]: Rule /Common/qux : after: /test
    May  2 22:15:33 ve11c info tmm1[5649]: Rule /Common/qux : ---
    May  2 22:15:33 ve11c info tmm1[5649]: Rule /Common/qux : before: /test?param1=value1
    May  2 22:15:33 ve11c info tmm1[5649]: Rule /Common/qux : after: /test?param1=value1
    May  2 22:15:40 ve11c info tmm[5649]: Rule /Common/qux : ---
    May  2 22:15:40 ve11c info tmm[5649]: Rule /Common/qux : before: /test?param1=value1&Context_1=123
    May  2 22:15:40 ve11c info tmm[5649]: Rule /Common/qux : after: /test?param1=value1
    May  2 22:15:45 ve11c info tmm1[5649]: Rule /Common/qux : ---
    May  2 22:15:45 ve11c info tmm1[5649]: Rule /Common/qux : before: /test?Context_1=123&param1=value1
    May  2 22:15:45 ve11c info tmm1[5649]: Rule /Common/qux : after: /test?param1=value1
    May  2 22:15:50 ve11c info tmm[5649]: Rule /Common/qux : ---
    May  2 22:15:50 ve11c info tmm[5649]: Rule /Common/qux : before: /test?Context_1=123&param1=value1&Context_2=456&param2=value2
    May  2 22:15:50 ve11c info tmm[5649]: Rule /Common/qux : after: /test?param1=value1&param2=value2
    
    • Rory_Hewitt_F5_'s avatar
      Rory_Hewitt_F5_
      Icon for Cirrus rankCirrus
      Hey @nitass, thanks for checking that. I suspect it could be just a Tclkit problem then...