Forum Discussion

stucky101_88485's avatar
stucky101_88485
Icon for Nimbostratus rankNimbostratus
Feb 23, 2013

We have "getfield" I need "trimfield"

Gurus

 

This is one of those things you'd think is super simple but I've been pulling my hair out.

 

There appear to be many ways to trim any occurence of a char/string within another string like a uri but it's always ANY ocurrence.

 

I want just the FIRST one trimmed. Basically I'm looking for the exact thing "getfield" does except that I wanna trim it when found so

 

"trimfield" ? I'd look into regex substitution but I know you should not ever use those if you can help it.

 

My scenario is simple. I just need to cut the first ocurccence of "/rma/" from a uri as part of a re-direct but the uri contains other instances of this string

 

later in various forms. Example:

 

/rma/rma.htm?_flowExecutionKey=_somestring

 

should become:

 

/rma.htm?_flowExecutionKey=_somestrin

 

or:

 

/rma/rma/something&rma=blalb

 

should become

 

/rma/something&rma=blalb

 

I have a dgl called "trim_left_uri" and I figured trimleft is the way to go so I added the string "/rma/" to the dgl and use the following code:

 

Check if uri needs left trimming

 

set field1 [getfield [HTTP::uri] "/" 2]

 

log local0. "field1 is $field1"

 

if { [class match /$field1/ equals trim_left_uri] } {

 

set new_uri [string trimleft [HTTP::uri] /$field1/]

 

problem is that trims this :

 

/rma/rma.htm?_flowExecutionKey=_somestring

 

to this:

 

/.htm?_flowExecutionKey=_something

 

I'm looking to trim the string literal "/rma/' not the character class [/rma].

 

Every other way to do this I've found has the same limitation where it's all or nothing for example "string map" - same issue.

 

It appears to me the easiest way to solve this would be to say "Split the uri by / and trim field 2" - done.

 

However, I cannot find such a command. Do I need the old regex subsitution after all ?

 

In bash that would be :

 

echo '/rma/rma/rma.htm/rma/flowExecutionKey=_mra' | sed 's%^/rma/\(.\+\)%\/\1%g'

 

/rma/rma.htm/rma/flowExecutionKey=_mra

 

--scratching head

 

8 Replies

  • So you tried string map? Something like this wouldn't work:

    
    string map {"/rma/rma" "/rma"} [HTTP::uri]
    
  • e.g.

     

     

    [root@ve10:Active] config b class trim_left_uri list

     

    class trim_left_uri {

     

    {

     

    "/rma/"

     

    "/test/"

     

    }

     

    }

     

    [root@ve10:Active] config b rule myrule list

     

    rule myrule {

     

    when HTTP_REQUEST {

     

    if { [set item [class match -name [HTTP::uri] contains trim_left_uri]] ne "" } {

     

    set idx [string first $item [HTTP::uri]]

     

    HTTP::uri [string replace [HTTP::uri] $idx [expr {$idx + [string length $item] - 1}] /]

     

    }

     

    }

     

    }

     

     

    [root@ve10:Active] config ssldump -Aed -nni 0.0 port 80

     

    New TCP connection 1: 172.28.19.251(55448) <-> 172.28.19.252(80)

     

    1361615316.4182 (0.0009) C>S

     

    ---------------------------------------------------------------

     

    HEAD /rma/rma/something&rma=blalb HTTP/1.1

     

    User-Agent: curl/7.15.5 (i686-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5

     

    Host: 172.28.19.252

     

    Accept: */*

     

    ---------------------------------------------------------------

     

    New TCP connection 2: 200.200.200.10(55448) <-> 200.200.200.101(80)

     

    1361615316.4193 (0.0009) C>S

     

    ---------------------------------------------------------------

     

    HEAD /rma/something&rma=blalb HTTP/1.1

     

    User-Agent: curl/7.15.5 (i686-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5

     

    Host: 172.28.19.252

     

    Accept: */*

     

    ---------------------------------------------------------------

     

  • Kevin

    /rma/rma was just something to prove a point. I don't know what any given uri will look like but I have seen

    several occurrances in one uri of the same string that I was trimming so I used the above to clarify the problem.

    I wanted a solution where I simply cut out the first "/rma/" and not worry what comes after that.

    I had tried

     string map {"/rma/" ""} [HTTP::uri] 
    since I really wanna trim but ran in to the same issue.

    Thanks for you reply though. I just saw there is another one that looks promising.

  • Nitass

     

    Thank you for this beautiful solution ! I had been looking at string replace and string first but I couldn't help feeling I was over engineering this.

     

    I assumed there was a much simpler function that already does that - guess not. As long as we avoid the evil regex I'm happy.

     

    Devcentral is great !!

     

     

    stucky

     

  • Nitass

     

    One more thing. I noticed you use "contains" to check for the string in the uri.

     

    I changed that to "starts_with" since I only want to match to begin with if the uri starts with "/rma/".

     

  • I changed that to "starts_with" since I only want to match to begin with if the uri starts with "/rma/".that is fine. i used "contains" because i am not sure where the string is in uri. anyway, i believe starts_with is better in performance.
  • I take it back. Your solution actually offers more than what I needed but that's even better. With this I can trim any first occurrence of the string in the uri so "contains" is back in.

     

    Awesome !