Skip to content

Commit aec14c4

Browse files
arturobernalgok2c
authored andcommitted
HTTPCORE-770: Introduced plusAsBlank parameter for dynamic configuration
- Added `plusAsBlank` flag to `URIBuilder` to dynamically configure whether '+' should be interpreted as a space in query parameters. - Implemented `setPlusAsBlank` method to update the flag and re-parse the query accordingly.
1 parent 6561c22 commit aec14c4

File tree

2 files changed

+56
-1
lines changed

2 files changed

+56
-1
lines changed

httpcore5/src/main/java/org/apache/hc/core5/net/URIBuilder.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ public static URIBuilder loopbackAddress() {
8888
private String fragment;
8989
private String encodedFragment;
9090

91+
private boolean plusAsBlank;
92+
9193
/**
9294
* Constructs an empty instance.
9395
*/
@@ -192,6 +194,33 @@ public Charset getCharset() {
192194
return charset;
193195
}
194196

197+
/**
198+
* Sets whether the plus sign ('+') should be interpreted as a blank space (' ') when parsing
199+
* the query parameters of the URI.
200+
* <p>
201+
* In HTTP URLs, query strings may contain spaces encoded as '+' characters or as '%20'.
202+
* This flag controls whether '+' is interpreted as a space or remains as a plus sign.
203+
* </p>
204+
*
205+
* <p>
206+
* If the query string was already set, calling this method will re-parse the query
207+
* using the updated flag. This ensures that the query parameters are processed correctly
208+
* based on the specified interpretation of the '+' character.
209+
* </p>
210+
*
211+
* @param plusAsBlank {@code true} to interpret '+' as a space, {@code false} to keep '+' as a literal plus sign.
212+
* @return this {@link URIBuilder} instance for method chaining.
213+
* @since 5.4
214+
*/
215+
public URIBuilder setPlusAsBlank(final boolean plusAsBlank) {
216+
this.plusAsBlank = plusAsBlank;
217+
// Re-parse the query string using the updated flag
218+
if (this.encodedQuery != null) {
219+
this.queryParams = parseQuery(this.encodedQuery, this.charset, this.plusAsBlank);
220+
}
221+
return this;
222+
}
223+
195224
private static final char QUERY_PARAM_SEPARATOR = '&';
196225
private static final char PARAM_VALUE_SEPARATOR = '=';
197226
private static final char PATH_SEPARATOR = '/';
@@ -402,7 +431,7 @@ private void digestURI(final URI uri, final Charset charset) {
402431
this.pathSegments = parsePath(uri.getRawPath(), charset);
403432
this.pathRootless = uri.getRawPath() == null || !uri.getRawPath().startsWith("/");
404433
this.encodedQuery = uri.getRawQuery();
405-
this.queryParams = parseQuery(uri.getRawQuery(), charset, false);
434+
this.queryParams = parseQuery(uri.getRawQuery(), charset, this.plusAsBlank);
406435
this.encodedFragment = uri.getRawFragment();
407436
this.fragment = uri.getFragment();
408437
this.charset = charset;

httpcore5/src/test/java/org/apache/hc/core5/net/TestURIBuilder.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,4 +973,30 @@ void testHttpUriWithEmptyHost() {
973973
.setFragment("fragment");
974974
Assertions.assertThrows(URISyntaxException.class, uribuilder::build);
975975
}
976+
977+
@Test
978+
void testSetPlusAsBlank() throws Exception {
979+
// Case 1: Plus as blank, "+" should be treated as space
980+
URIBuilder uriBuilder = new URIBuilder("http://localhost?param=hello+world")
981+
.setPlusAsBlank(true);
982+
List<NameValuePair> params = uriBuilder.getQueryParams();
983+
Assertions.assertEquals("hello world", params.get(0).getValue());
984+
985+
// Case 2: Plus as plus, "+" should remain "+"
986+
uriBuilder = new URIBuilder("http://localhost?param=hello+world")
987+
.setPlusAsBlank(false);
988+
params = uriBuilder.getQueryParams();
989+
Assertions.assertEquals("hello+world", params.get(0).getValue());
990+
991+
// Case 3: '%20' always interpreted as space
992+
uriBuilder = new URIBuilder("http://localhost?param=hello%20world")
993+
.setPlusAsBlank(true);
994+
params = uriBuilder.getQueryParams();
995+
Assertions.assertEquals("hello world", params.get(0).getValue());
996+
997+
uriBuilder = new URIBuilder("http://localhost?param=hello%20world")
998+
.setPlusAsBlank(false);
999+
params = uriBuilder.getQueryParams();
1000+
Assertions.assertEquals("hello world", params.get(0).getValue());
1001+
}
9761002
}

0 commit comments

Comments
 (0)