Skip to content

Commit fa29494

Browse files
fix: clear remaining Sonar findings on forwarded package (#91)
Follow-up to #89 clearing the two remaining SonarCloud issues on the new `de.cuioss.http.forwarded` package so it reports zero: - **S2589** (`ForwardedResolverConfig.parseAllowlist`): the `commaSeparated == null` check was flagged "always false" because the `@NullMarked` package makes the parameter implicitly non-null — yet the method genuinely accepts null (per its Javadoc). Annotating the parameter `@Nullable` makes the nullable contract explicit and the null-check legitimate. - **S3398** (`RfcForwardedParser`): `unquote` is only used by the inner `Accumulator`, so it is moved into that class. No behavior change; existing tests unaffected. --------- Co-authored-by: Oliver Wolff <23139298+cuioss@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
1 parent b5f05ee commit fa29494

3 files changed

Lines changed: 36 additions & 25 deletions

File tree

cui-http-core/src/main/java/de/cuioss/http/forwarded/ForwardedResolverConfig.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package de.cuioss.http.forwarded;
1717

1818
import de.cuioss.http.security.config.SecurityConfiguration;
19+
import org.jspecify.annotations.Nullable;
1920

2021
import java.net.InetAddress;
2122
import java.util.*;
@@ -132,7 +133,7 @@ public static Builder builder() {
132133
* @param commaSeparated the raw comma-separated allowlist (may be {@code null})
133134
* @return an unmodifiable set of normalized context paths in input order
134135
*/
135-
public static Set<String> parseAllowlist(String commaSeparated) {
136+
public static Set<String> parseAllowlist(@Nullable String commaSeparated) {
136137
Set<String> allowed = new LinkedHashSet<>();
137138
if (commaSeparated == null || commaSeparated.isBlank()) {
138139
return Collections.unmodifiableSet(allowed);

cui-http-core/src/main/java/de/cuioss/http/forwarded/RfcForwardedParser.java

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,30 @@ private void apply(String pair) {
8989
}
9090
}
9191
}
92+
93+
/**
94+
* Strips surrounding double quotes and unescapes {@code \\x} sequences; returns non-quoted
95+
* input unchanged.
96+
*/
97+
private static String unquote(String value) {
98+
if (value.length() < 2 || value.charAt(0) != '"' || value.charAt(value.length() - 1) != '"') {
99+
return value;
100+
}
101+
StringBuilder out = new StringBuilder(value.length() - 2);
102+
boolean escaped = false;
103+
for (int i = 1; i < value.length() - 1; i++) {
104+
char c = value.charAt(i);
105+
if (escaped) {
106+
out.append(c);
107+
escaped = false;
108+
} else if (c == '\\') {
109+
escaped = true;
110+
} else {
111+
out.append(c);
112+
}
113+
}
114+
return out.toString();
115+
}
92116
}
93117

94118
/**
@@ -121,28 +145,4 @@ private static List<String> splitTopLevel(String input, char separator) {
121145
parts.add(current.toString());
122146
return parts;
123147
}
124-
125-
/**
126-
* Strips surrounding double quotes and unescapes {@code \\x} sequences; returns non-quoted
127-
* input unchanged.
128-
*/
129-
private static String unquote(String value) {
130-
if (value.length() < 2 || value.charAt(0) != '"' || value.charAt(value.length() - 1) != '"') {
131-
return value;
132-
}
133-
StringBuilder out = new StringBuilder(value.length() - 2);
134-
boolean escaped = false;
135-
for (int i = 1; i < value.length() - 1; i++) {
136-
char c = value.charAt(i);
137-
if (escaped) {
138-
out.append(c);
139-
escaped = false;
140-
} else if (c == '\\') {
141-
escaped = true;
142-
} else {
143-
out.append(c);
144-
}
145-
}
146-
return out.toString();
147-
}
148148
}

cui-http-core/src/test/java/de/cuioss/http/forwarded/RfcForwardedParserTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ void handlesQuotedValues() {
4646
assertEquals("a,b", parsed.host().orElseThrow());
4747
}
4848

49+
@Test
50+
@DisplayName("unescapes backslash-escaped characters inside a quoted value")
51+
void unescapesEscapedCharacters() {
52+
// host="a\"b" -> a"b ; for="x\\y" -> x\y
53+
RfcForwardedParser.Parsed parsed = RfcForwardedParser.parse("host=\"a\\\"b\";for=\"x\\\\y\"");
54+
55+
assertEquals("a\"b", parsed.host().orElseThrow());
56+
assertEquals("x\\y", parsed.forValues().getFirst());
57+
}
58+
4959
@Test
5060
@DisplayName("takes the first proto/host across elements")
5161
void firstProtoWins() {

0 commit comments

Comments
 (0)