Layer7 API Management

 View Only

 Why does Evaluate Regular expression assertion keep replacing matches even though "Repeat successful replacements" is unchecked

Jump to Best Answer
James Lum's profile image
James Lum posted Apr 21, 2024 05:39 PM

Hi,

I am trying to use the Evaluate Regular Expression assertion to inject 2 xmlns attributes into a request.

Replace

">

with:

" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

I have "Match and replace" checked and "Repeat successful replacements" UNchecked.

When I test the policy it IS replacing the 1st instance of ">, but then it seems to be replacing ALL instances also.

The help says that if the "Repeat successful replacements" is unchecked, it should just do the replacement ONCE, but that doesn't seem to be what it is doing.

Can anyone tell me how I can get the assertion to replace  only the 1st matching instance?

Thanks,

Jim

Joseph Fry's profile image
Broadcom Employee Joseph Fry Best Answer

Thanks for the fun challenge!  Saw this come in last week while I was out of town and was excited to give it a shot.

Here is a regex that will only replace the first instance of "> in a string (single or multiline):

^(.*?)">(.*)


This creates two matches...

$1 is everything before the first ">, this is represented as ^(.*?) where the ^ tells it to start at the beginning of the string, .* means to match zero or more characters and ? means be lazy (repeat the fewest times possible).  
$2 is everything after the first match, represented by (.*) again, but because there is no ? it will be greedy and match to the end of the string.

Then you just use the $1 and $2 in your replacement string like so:

$1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">$2

 Here is a screenshot of it in action:

Joseph Fry's profile image
Broadcom Employee Joseph Fry

Oh.. if you want it to do the replacement on the first "> of every line, simply make $2 lazy too, like so:

^(.*?)">(.*?)

The extra ? tells it that $2 should only run to the next instance of ">.

And just to clarify the "Repeat successful replacements" option... that's to do recursive replacements, basically run the regex replacement again on the resulting string.  For example if you had a string that had a ton of extra spaces in it, you could use regex to replace double spaces with a single space; but anywhere there were 3 or more spaces in a row would still have double spaces, so you would repeat the replacement until no matches are found.

Joseph Fry's profile image
Broadcom Employee Joseph Fry

One other thing to note.  When doing a match and replace, it actually modifies the source variable.  So you will want to use ${temprequest} in subsequent assertions to use the results of your replace.

The context variable field on the destination pane (where you set mytest) is only used to output capture groups and won't get you what your looking for.

Took me a while to figure that out the first time.  The only clue is the "OK (Overwrite)" that appears in the source box.  The fact that it overwrites the source is strangely not in the documentation.