Forum Discussion

agidwani_102403's avatar
agidwani_102403
Icon for Nimbostratus rankNimbostratus
Feb 25, 2008

STREAM::max_matchsize - HELP - Urgent

All,

 

 

We are trying to do a URI rewrite and are running into some kind of buffer limitation with streams.

 

 

We get a error message when using the following streams directive

 

 

STREAMS::max_matchsize 8192

 

 

 

01070151:3: Rule [global_rewrite] error:

 

line 21: [command is not valid in current event context (HTTP_REQUEST)] [STREAM::max_matchsize 8192]

 

 

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

 

 

 

when HTTP_REQUEST {

 

set uri [string tolower [HTTP::uri]]

 

if { ($uri contains "/global/") }

 

{ pool acecomm }

 

elseif { ($uri contains "/AC4AC/") or

 

($uri contains "/awchs54beta/")

 

}

 

{

 

if { $uri contains "/hscs.asmx" } {

 

pool acecomm

 

Change the URI of the request, preserving the query arguments, if any.

 

set args [findstr $uri "?"]

 

HTTP::uri "/global/hscs.asmx$args"

 

 

if {[HTTP::method] equals "POST"} {

 

Look for /*/hscs.asmx and replace * with "global"

 

(if you change "global" here you need to change the hard-coded length of 6 below)

 

Note that this does not fix the Content-Length so we need to do that below

 

STREAM::expression {@/[^/]*/[Hh][Ss][Cc][Ss].[Aa][Ss][Mm][Xx]@/global/hscs.asmx@}

 

STREAM::enable

 

 

Determine what the original path was

 

set origpath [findstr $uri "/" 1 "/"]

 

 

Store original content-length for POST data

 

set origlen [HTTP::header "Content-Length"]

 

 

Assume replacement string ("global") is 6 characters long, determine difference in

 

length between "global" and the replacement path

 

set length_change [expr {6 - [string length $origpath] } ]

 

set newlen [expr {$origlen + $length_change}]

 

 

Set new content length, assuming the stream profile performed exactly one replacement

 

HTTP::header remove "Content-Length"

 

HTTP::header insert "Content-Length" [expr {$origlen + $length_change}]

 

 

log local0. "origpath=$origpath, change=$length_change, origlen=$origlen"

 

log local0. "Content length after: [HTTP::header Content-length]"

 

 

}

 

}

 

}

 

}

9 Replies

  • Hi arvgidwani,

     

     

    I'm not sure how relevant this is, but the STREAM::max_matchsize command only seems to be valid in the STREAM_MATCHED command (not in RULE_INIT, CLIENT_ACCEPTED or HTTP_REQUEST). According to the wiki, the STREAM_MATCHED event is triggered when the stream filter matches the expression against the a part of the payload. To be honest, I'm not sure why you'd want to set the buffer size after you've already made a match. It would seem logical to set the buffer size prior to the stream expression being evaluated.

     

     

    What is the actual issue you're seeing prior to trying to use the max_matchsize command. Also, what version are you running?

     

     

    Aaron
  • Lance_Simon_557's avatar
    Lance_Simon_557
    Historic F5 Account
    Aaron,

     

     

    Apparently the iRule works when the payload is less than 4096 bytes. This is why he wants to use the max_matchsize command to see what he can do to "buffer" more payload than 4096 to get this to work.

     

     

    I don't think the stream will buffer the payload.

     

     

    Lance
  • Hey Lance,

     

     

    I'm not sure... Anyone know what the command does and/or a suggestion for the issue?

     

     

    Aaron
  • spark_86682's avatar
    spark_86682
    Historic F5 Account
    I'll look up later what that command does, but if you want to experiment with it, I think it should be callable (by a bizarre quirk of fate) in LB_SELECTED, which should be before any serverside data is returned.
  • One of the F5 expert was able to help write the script, We are running version 9.3.

     

     

    Production iRule

     

    when HTTP_REQUEST {

     

    set uri [string tolower [HTTP::uri]]

     

    if { ($uri contains "/global/") }

     

    { pool acecomm }

     

    elseif { ($uri contains "/name1/") or

     

    ($uri contains "/name2/") or

     

    ($uri contains "/blah/")

     

    }

     

    {

     

    if { $uri contains "/hscs.asmx" } {

     

    pool acecomm

     

    Change the URI of the request, preserving the query arguments, if any.

     

    set args [findstr $uri "?"]

     

    HTTP::uri "/global/hscs.asmx$args"

     

     

    if {[HTTP::method] equals "POST"} {

     

    Determine what the original path was

     

    set origpath [findstr $uri "/" 1 "/"]

     

     

    Determine the search regex (case-insensitive)

     

    set search ""

     

    set index 0

     

    while {$index < [string length $origpath]} {

     

    set char [string index $origpath $index]

     

    set search "$search\[$char[string toupper $char]\]"

     

    incr index

     

    }

     

     

    Look for /*/hscs.asmx and replace * with "global"

     

    (if you change "global" here you need to change the hard-coded length of 6 below)

     

    Note that this does not fix the Content-Length so we need to do that below

     

    STREAM::expression "@/$search/\[Cc\]\[Oo\]\[Mm\]\[Pp\].\[Aa\]\[Ss\]\[Mm\]\[Xx\]@/global/hscs.asmx@"

     

    STREAM::enable

     

     

    Store original content-length for POST data

     

    set origlen [HTTP::header "Content-Length"]

     

     

    Assume replacement string ("global") is 6 characters long, determine difference in

     

    length between "global" and the replacement path

     

    set length_change [expr {6 - [string length $origpath] } ]

     

     

    Set new content length, assuming the stream profile performed exactly one replacement

     

    HTTP::header remove "Content-Length"

     

    HTTP::header insert "Content-Length" [expr {$origlen + $length_change}]

     

     

    log local0. "search path $search"

     

    log local0. "origpath=$origpath, change=$length_change, origlen=$origlen"

     

    log local0. "origpath=$origpath, Content len after: [HTTP::header Content-length]"

     

    }

     

    }

     

    }

     

    }
  • my 2 cents

     

     

    to change the data part...may be we can use HTTP_REQUEST_DATA event + regsub command. performance of STREAM profile might be better but using HTTP_REQUEST_DATA, iRule might be easier

     

     

    for example, (not tested)

     

    when HTTP_REQUEST {

     

     

    if {[HTTP::method] equals "POST"} {

     

    set len [HTTP::header Content-Length]

     

    HTTP::collect $len

     

    }

     

    }

     

    when HTTP_REQUEST_DATA {

     

    regsub -nocase {/$search/\[Cc\]\[Oo\]\[Mm\]\[Pp\].\[Aa\]\[Ss\]\[Mm\]\[Xx\]} [HTTP::payload] "/global/hscs.asmx" newpayload

     

    HTTP::payload replace 0 $len $newpayload

     

    }

     

     

    BIG-IP should be able to handle content-length modification...
  • Hi Spark,

     

     

    if you think of it, could you provide more detail on STREAM::max_matchsize?

     

     

    Thanks,

     

    Aaron
  • spark_86682's avatar
    spark_86682
    Historic F5 Account
    Basically, the STREAM profile will buffer data for partial matches; if more than "max_matchsize" would be buffered, the connection will be torn down. This way a regex like "foobarba[^z]+" won't keep matching until the box runs out of memory. The default is 4K, and STREAM::max_matchsize can be use to set it to something else.
  • FYI, I hit this issue recently. I'm not sure I fully understand what a partial match is but regardless, I doubled the value of the buffer, within the HTTP_RESPONSE event:

    when HTTP_RESPONSE {
      STREAM::max_matchsize 8192
      STREAM::enable
      ...
    }
    

    Note, the actual response payload that was giving me issues was around 64kB. Considering the issue was intermittent, it's possible the buffer relates to all traffic handled by the Virtual Server, not each connection.

    Using the STREAM::max_matchsize command in the STREAM_MATCHED event (as I'd seen suggested elsewhere) doesn't work.