Skip to content

Commit c2191e3

Browse files
daguimurstoyanchev
authored andcommitted
Fix fragment parsing for relative URI in RfcUriParser
When parsing a relative URI such as `path2#foo`, RfcUriParser's SCHEME_OR_PATH state advanced to FRAGMENT without moving the component index past the `#` character, so the captured fragment included the entire input (`path2#foo`) instead of just `foo`. As a result, `toUriString()` produced `path2#path2#foo`. Update the SCHEME_OR_PATH `#` transition to advance the component index to `i + 1`, matching the sibling `?` -> QUERY transition in the same state and every other `-> FRAGMENT` transition in the parser. URIs with a `/` in the path are unaffected because they leave SCHEME_OR_PATH for PATH on the first slash; the WhatWG parser already handled this case correctly. Closes gh-36762 Signed-off-by: daguimu <daguimu.geek@gmail.com>
1 parent 175c1f9 commit c2191e3

2 files changed

Lines changed: 22 additions & 1 deletion

File tree

spring-web/src/main/java/org/springframework/web/util/RfcUriParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public void handleNext(InternalParser parser, char c, int i) {
178178
parser.capturePath().advanceTo(QUERY, i + 1);
179179
break;
180180
case '#':
181-
parser.capturePath().advanceTo(FRAGMENT);
181+
parser.capturePath().advanceTo(FRAGMENT, i + 1);
182182
break;
183183
}
184184
}

spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,27 @@ void fromUriStringInvalidIPv6Host(ParserType parserType) {
270270
UriComponentsBuilder.fromUriString("http://[1abc:2abc:3abc::5ABC:6abc:8080/resource", parserType));
271271
}
272272

273+
@ParameterizedTest // gh-36759
274+
@EnumSource
275+
void fromUriStringRelativeUriWithFragment(ParserType parserType) {
276+
UriComponents result = UriComponentsBuilder.fromUriString("path2#foo", parserType).build();
277+
assertThat(result.getScheme()).isNull();
278+
assertThat(result.getHost()).isNull();
279+
assertThat(result.getPath()).isEqualTo("path2");
280+
assertThat(result.getFragment()).isEqualTo("foo");
281+
assertThat(result.toUriString()).isEqualTo("path2#foo");
282+
}
283+
284+
@ParameterizedTest // gh-36759
285+
@EnumSource
286+
void fromUriStringRelativeUriWithEmptyFragment(ParserType parserType) {
287+
UriComponents result = UriComponentsBuilder.fromUriString("path2#", parserType).build();
288+
assertThat(result.getScheme()).isNull();
289+
assertThat(result.getHost()).isNull();
290+
assertThat(result.getPath()).isEqualTo("path2");
291+
assertThat(result.getFragment()).isNull();
292+
}
293+
273294
@ParameterizedTest // see SPR-11970
274295
@EnumSource
275296
void fromUriStringNoPathWithReservedCharInQuery(ParserType parserType) {

0 commit comments

Comments
 (0)