Skip to content

Commit d42d152

Browse files
authored
Merge pull request #1822 from fl4via/backport-features_2.4.x
[UNDERTOW - 2301 / 2273 / 2110 / 2288 / 1748 / 2404] Port features to 2.4.x
2 parents 68f308f + 2c20a30 commit d42d152

File tree

10 files changed

+543
-67
lines changed

10 files changed

+543
-67
lines changed

core/src/main/java/io/undertow/Undertow.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ public synchronized void start() {
181181
if (listener.type == ListenerType.HTTP) {
182182
HttpOpenListener openListener = new HttpOpenListener(buffers, undertowOptions);
183183
HttpHandler handler = rootHandler;
184-
if (http2) {
184+
if (http2 || listener.http2Enabled) {
185185
handler = new Http2UpgradeHandler(handler);
186186
}
187187
openListener.setRootHandler(handler);
@@ -203,7 +203,7 @@ public synchronized void start() {
203203
HttpOpenListener httpOpenListener = new HttpOpenListener(buffers, undertowOptions);
204204
httpOpenListener.setRootHandler(rootHandler);
205205

206-
if (http2) {
206+
if (http2 || listener.http2Enabled) {
207207
AlpnOpenListener alpn = new AlpnOpenListener(buffers, undertowOptions, httpOpenListener);
208208
Http2OpenListener http2Listener = new Http2OpenListener(buffers, undertowOptions);
209209
http2Listener.setRootHandler(rootHandler);
@@ -322,6 +322,7 @@ private static class ListenerConfig {
322322
final HttpHandler rootHandler;
323323
final OptionMap overrideSocketOptions;
324324
final boolean useProxyProtocol;
325+
final boolean http2Enabled;
325326

326327
private ListenerConfig(final ListenerType type, final int port, final String host, KeyManager[] keyManagers, TrustManager[] trustManagers, HttpHandler rootHandler) {
327328
this.type = type;
@@ -333,6 +334,7 @@ private ListenerConfig(final ListenerType type, final int port, final String hos
333334
this.sslContext = null;
334335
this.overrideSocketOptions = OptionMap.EMPTY;
335336
this.useProxyProtocol = false;
337+
this.http2Enabled = false;
336338
}
337339

338340
private ListenerConfig(final ListenerType type, final int port, final String host, SSLContext sslContext, HttpHandler rootHandler) {
@@ -345,6 +347,7 @@ private ListenerConfig(final ListenerType type, final int port, final String hos
345347
this.sslContext = sslContext;
346348
this.overrideSocketOptions = OptionMap.EMPTY;
347349
this.useProxyProtocol = false;
350+
this.http2Enabled = false;
348351
}
349352

350353
private ListenerConfig(final ListenerBuilder listenerBuilder) {
@@ -357,6 +360,7 @@ private ListenerConfig(final ListenerBuilder listenerBuilder) {
357360
this.sslContext = listenerBuilder.sslContext;
358361
this.overrideSocketOptions = listenerBuilder.overrideSocketOptions;
359362
this.useProxyProtocol = listenerBuilder.useProxyProtocol;
363+
this.http2Enabled = listenerBuilder.http2Enabled;
360364
}
361365
}
362366

@@ -371,6 +375,7 @@ public static final class ListenerBuilder {
371375
HttpHandler rootHandler;
372376
OptionMap overrideSocketOptions = OptionMap.EMPTY;
373377
boolean useProxyProtocol;
378+
boolean http2Enabled;
374379

375380
public ListenerBuilder setType(ListenerType type) {
376381
this.type = type;
@@ -416,6 +421,11 @@ public ListenerBuilder setUseProxyProtocol(boolean useProxyProtocol) {
416421
this.useProxyProtocol = useProxyProtocol;
417422
return this;
418423
}
424+
425+
public ListenerBuilder setHttp2Enabled(boolean http2Enabled) {
426+
this.http2Enabled = http2Enabled;
427+
return this;
428+
}
419429
}
420430

421431
public static final class Builder {

core/src/main/java/io/undertow/attribute/ExchangeAttributeParser.java

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public ExchangeAttribute parse(final String valueString) {
7575
final List<ExchangeAttribute> attributes = new ArrayList<>();
7676
int pos = 0;
7777
int state = 0; //0 = literal, 1 = %, 2 = %{, 3 = $, 4 = ${
78+
int braceDepth = 0; // Track the depth of curly braces
7879
for (int i = 0; i < valueString.length(); ++i) {
7980
char c = valueString.charAt(i);
8081
switch (state) {
@@ -95,6 +96,7 @@ public ExchangeAttribute parse(final String valueString) {
9596
case 1: {
9697
if (c == '{') {
9798
state = 2;
99+
braceDepth++;
98100
} else if (c == '%') {
99101
//literal percent
100102
attributes.add(wrap(new ConstantExchangeAttribute("%")));
@@ -108,16 +110,22 @@ public ExchangeAttribute parse(final String valueString) {
108110
break;
109111
}
110112
case 2: {
111-
if (c == '}') {
112-
attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
113-
pos = i + 1;
114-
state = 0;
113+
if (c == '{') {
114+
braceDepth++;
115+
} else if (c == '}') {
116+
braceDepth--;
117+
if (braceDepth == 0) {
118+
attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
119+
pos = i + 1;
120+
state = 0;
121+
}
115122
}
116123
break;
117124
}
118125
case 3: {
119126
if (c == '{') {
120127
state = 4;
128+
braceDepth++;
121129
} else if (c == '$') {
122130
//literal dollars
123131
attributes.add(wrap(new ConstantExchangeAttribute("$")));
@@ -132,30 +140,26 @@ public ExchangeAttribute parse(final String valueString) {
132140
}
133141
case 4: {
134142
if (c == '}') {
135-
attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
136-
pos = i + 1;
137-
state = 0;
143+
braceDepth--;
144+
if (braceDepth == 0) {
145+
attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
146+
pos = i + 1;
147+
state = 0;
148+
}
149+
} else if (c == '{') {
150+
braceDepth++;
138151
}
139152
break;
140153
}
141-
142154
}
143155
}
144-
switch (state) {
145-
case 0:
146-
case 1:
147-
case 3:{
148-
if(pos != valueString.length()) {
149-
attributes.add(wrap(parseSingleToken(valueString.substring(pos))));
150-
}
151-
break;
152-
}
153-
case 2:
154-
case 4: {
155-
throw UndertowMessages.MESSAGES.mismatchedBraces(valueString);
156-
}
156+
if (state != 0 || braceDepth != 0) {
157+
throw UndertowMessages.MESSAGES.mismatchedBraces(valueString);
158+
}
159+
if (pos != valueString.length()) {
160+
attributes.add(wrap(parseSingleToken(valueString.substring(pos))));
157161
}
158-
if(attributes.size() == 1) {
162+
if (attributes.size() == 1) {
159163
return attributes.get(0);
160164
}
161165
return new CompositeExchangeAttribute(attributes.toArray(new ExchangeAttribute[attributes.size()]));

core/src/main/java/io/undertow/server/handlers/builder/PredicatedHandlersParser.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,11 @@ static Node parse(final String string, Deque<Token> tokens, boolean topLevel) {
363363
if(token.getToken().equals(";") && tokens.peek()!=null && tokens.peek().getToken().equals(ELSE)) {
364364
// something() -> predicate; ELSE predicate; - dont end processing since its followed by ELSE and its singular block
365365
continue;
366+
} else if (token.getToken().equals("\n") && tokens.peek() != null && isOperator(tokens.peek().getToken())) {
367+
// predicate
368+
// OPERATOR predicate
369+
// -> handeler
370+
continue;
366371
}
367372
handleLineEnd(string, operatorStack, output, blocks);
368373
} else if (isSpecialChar(token.getToken())) {
@@ -623,6 +628,7 @@ public static Deque<Token> tokenize(final String string) {
623628
boolean inVariable = false;
624629

625630
int pos = 0;
631+
int braceCount = 0;
626632
StringBuilder current = new StringBuilder();
627633
Deque<Token> ret = new ArrayDeque<>();
628634
while (pos < string.length()) {
@@ -647,6 +653,23 @@ public static Deque<Token> tokenize(final String string) {
647653
}
648654
} else {
649655
switch (c) {
656+
case '#':
657+
final Token previous = ret.peekLast();
658+
if(previous == null ||(previous != null && previous.getToken().equals("\n"))) {
659+
//its either first line ever or new line
660+
pos++;
661+
while (pos < string.length()) {
662+
char skip = string.charAt(pos);
663+
if(skip == '\n' || skip == '\r') {
664+
break;
665+
}
666+
pos++;
667+
}
668+
break;
669+
} else {
670+
current.append(c);
671+
break;
672+
}
650673
case ' ':
651674
case '\t': {
652675
if (current.length() != 0) {
@@ -657,7 +680,9 @@ public static Deque<Token> tokenize(final String string) {
657680
}
658681
case '\r':
659682
case '\n': {
660-
if (current.length() != 0) {
683+
if(braceCount>0) {
684+
break;
685+
} else if (current.length() != 0) {
661686
ret.add(new Token(current.toString(), pos));
662687
current.setLength(0);
663688
}
@@ -673,6 +698,19 @@ public static Deque<Token> tokenize(final String string) {
673698
case ']':
674699
case '{':
675700
case '}': {
701+
switch (c) {
702+
case '(':
703+
case '[':
704+
case '{':
705+
braceCount++;
706+
break;
707+
case ')':
708+
case ']':
709+
case '}':
710+
braceCount--;
711+
break;
712+
default:
713+
}
676714
if (inVariable) {
677715
current.append(c);
678716
if (c == '}') {

0 commit comments

Comments
 (0)