Skip to content

Commit

Permalink
Merge pull request #1575 from xjusko/UNDERTOW-2273
Browse files Browse the repository at this point in the history
[UNDERTOW-2273] Change ExchangeAttributeParser so it correctly handle…
  • Loading branch information
baranowb authored Sep 4, 2024
2 parents 91a9dd8 + f9865bd commit d42e47a
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public ExchangeAttribute parse(final String valueString) {
final List<ExchangeAttribute> attributes = new ArrayList<>();
int pos = 0;
int state = 0; //0 = literal, 1 = %, 2 = %{, 3 = $, 4 = ${
int braceDepth = 0; // Track the depth of curly braces
for (int i = 0; i < valueString.length(); ++i) {
char c = valueString.charAt(i);
switch (state) {
Expand All @@ -95,6 +96,7 @@ public ExchangeAttribute parse(final String valueString) {
case 1: {
if (c == '{') {
state = 2;
braceDepth++;
} else if (c == '%') {
//literal percent
attributes.add(wrap(new ConstantExchangeAttribute("%")));
Expand All @@ -108,16 +110,22 @@ public ExchangeAttribute parse(final String valueString) {
break;
}
case 2: {
if (c == '}') {
attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
pos = i + 1;
state = 0;
if (c == '{') {
braceDepth++;
} else if (c == '}') {
braceDepth--;
if (braceDepth == 0) {
attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
pos = i + 1;
state = 0;
}
}
break;
}
case 3: {
if (c == '{') {
state = 4;
braceDepth++;
} else if (c == '$') {
//literal dollars
attributes.add(wrap(new ConstantExchangeAttribute("$")));
Expand All @@ -132,30 +140,26 @@ public ExchangeAttribute parse(final String valueString) {
}
case 4: {
if (c == '}') {
attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
pos = i + 1;
state = 0;
braceDepth--;
if (braceDepth == 0) {
attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
pos = i + 1;
state = 0;
}
} else if (c == '{') {
braceDepth++;
}
break;
}

}
}
switch (state) {
case 0:
case 1:
case 3:{
if(pos != valueString.length()) {
attributes.add(wrap(parseSingleToken(valueString.substring(pos))));
}
break;
}
case 2:
case 4: {
throw UndertowMessages.MESSAGES.mismatchedBraces(valueString);
}
if (state != 0 || braceDepth != 0) {
throw UndertowMessages.MESSAGES.mismatchedBraces(valueString);
}
if (pos != valueString.length()) {
attributes.add(wrap(parseSingleToken(valueString.substring(pos))));
}
if(attributes.size() == 1) {
if (attributes.size() == 1) {
return attributes.get(0);
}
return new CompositeExchangeAttribute(attributes.toArray(new ExchangeAttribute[attributes.size()]));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.undertow.attribute;

import org.junit.Assert;
import org.junit.Test;

import java.util.Collections;

public class ExchangeAttributeParserTest {

@Test
public void testSimpleNestedAttribute() {
ExchangeAttributeParser parser = new ExchangeAttributeParser(ExchangeAttributeParserTest.class.getClassLoader(), Collections.emptyList());
String attributeString = "%{myCustomAttr:%{REQUEST_LINE}}";
ExchangeAttribute attribute = parser.parse(attributeString);
// The attribute should be parsed as a single nested attribute, not as a composite of multiple attributes
Assert.assertEquals("Parsed attribute string should match input", attributeString, attribute.toString());
Assert.assertFalse("Attribute should not be of CompositeExchangeAttribute type", attribute instanceof CompositeExchangeAttribute);
}

@Test
public void testComplexNestedAttribute() {
ExchangeAttributeParser parser = new ExchangeAttributeParser(ExchangeAttributeParserTest.class.getClassLoader(), Collections.emptyList());
String attributeString = "%{myCustomAttr:%{anotherCustomAttr:%{REQUEST_LINE}}-%{REQUEST_METHOD}}";
ExchangeAttribute attribute = parser.parse(attributeString);
// The attribute should be parsed as a single nested attribute, not as a composite of multiple attributes
Assert.assertFalse("Attribute should not be of CompositeExchangeAttribute type", attribute instanceof CompositeExchangeAttribute);
Assert.assertEquals("Parsed attribute string should match input", attributeString, attribute.toString());
}

@Test
public void testSimpleAttribute() {
ExchangeAttributeParser parser = new ExchangeAttributeParser(ExchangeAttributeParserTest.class.getClassLoader(), Collections.emptyList());
String attributeString = "%{REQUEST_LINE}";
ExchangeAttribute attribute = parser.parse(attributeString);
Assert.assertTrue("Attribute should be of RequestLineAttribute type", attribute instanceof RequestLineAttribute);
Assert.assertEquals("Parsed attribute string should match input", attributeString, attribute.toString());
}

}

0 comments on commit d42e47a

Please sign in to comment.