Skip to content

Commit 1841516

Browse files
committed
Add option for setting max query params
Relates to: quarkusio/quarkus#47431
1 parent 61c518d commit 1841516

File tree

7 files changed

+94
-5
lines changed

7 files changed

+94
-5
lines changed

vertx-core/src/main/generated/io/vertx/core/http/HttpServerOptionsConverter.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, HttpSer
8787
obj.setMaxFormBufferedBytes(((Number)member.getValue()).intValue());
8888
}
8989
break;
90+
case "maxQueryParams":
91+
if (member.getValue() instanceof Number) {
92+
obj.setMaxQueryParams(((Number)member.getValue()).intValue());
93+
}
94+
break;
9095
case "initialSettings":
9196
if (member.getValue() instanceof JsonObject) {
9297
obj.setInitialSettings(new io.vertx.core.http.Http2Settings((io.vertx.core.json.JsonObject)member.getValue()));
@@ -214,6 +219,7 @@ static void toJson(HttpServerOptions obj, java.util.Map<String, Object> json) {
214219
json.put("maxFormAttributeSize", obj.getMaxFormAttributeSize());
215220
json.put("maxFormFields", obj.getMaxFormFields());
216221
json.put("maxFormBufferedBytes", obj.getMaxFormBufferedBytes());
222+
json.put("maxQueryParams", obj.getMaxQueryParams());
217223
if (obj.getInitialSettings() != null) {
218224
json.put("initialSettings", obj.getInitialSettings().toJson());
219225
}

vertx-core/src/main/java/io/vertx/core/http/HttpServerOptions.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ public class HttpServerOptions extends NetServerOptions {
104104
*/
105105
public static final int DEFAULT_MAX_FORM_BUFFERED_SIZE = 1024;
106106

107+
/**
108+
* Default max number of query params = 1024
109+
*/
110+
public static final int DEFAULT_MAX_QUERY_PARAMS = 1024;
111+
107112
/**
108113
* Default value of whether 100-Continue should be handled automatically = {@code false}
109114
*/
@@ -222,6 +227,7 @@ public class HttpServerOptions extends NetServerOptions {
222227
private int maxFormAttributeSize;
223228
private int maxFormFields;
224229
private int maxFormBufferedBytes;
230+
private int maxQueryParams;
225231
private Http2Settings initialSettings;
226232
private boolean http2ClearTextEnabled;
227233
private int http2ConnectionWindowSize;
@@ -271,6 +277,7 @@ public HttpServerOptions(HttpServerOptions other) {
271277
this.maxFormAttributeSize = other.getMaxFormAttributeSize();
272278
this.maxFormFields = other.getMaxFormFields();
273279
this.maxFormBufferedBytes = other.getMaxFormBufferedBytes();
280+
this.maxQueryParams = other.getMaxQueryParams();
274281
this.initialSettings = other.initialSettings != null ? new Http2Settings(other.initialSettings) : null;
275282
this.http2ClearTextEnabled = other.http2ClearTextEnabled;
276283
this.http2ConnectionWindowSize = other.http2ConnectionWindowSize;
@@ -328,6 +335,7 @@ private void init() {
328335
maxFormAttributeSize = DEFAULT_MAX_FORM_ATTRIBUTE_SIZE;
329336
maxFormFields = DEFAULT_MAX_FORM_FIELDS;
330337
maxFormBufferedBytes = DEFAULT_MAX_FORM_BUFFERED_SIZE;
338+
maxQueryParams = DEFAULT_MAX_QUERY_PARAMS;
331339
initialSettings = new Http2Settings().setMaxConcurrentStreams(DEFAULT_INITIAL_SETTINGS_MAX_CONCURRENT_STREAMS);
332340
http2ClearTextEnabled = DEFAULT_HTTP2_CLEAR_TEXT_ENABLED;
333341
http2ConnectionWindowSize = DEFAULT_HTTP2_CONNECTION_WINDOW_SIZE;
@@ -887,6 +895,24 @@ public HttpServerOptions setMaxFormBufferedBytes(int maxFormBufferedBytes) {
887895
return this;
888896
}
889897

898+
/**
899+
* @return Returns the maximum number of query params
900+
*/
901+
public int getMaxQueryParams() {
902+
return maxQueryParams;
903+
}
904+
905+
/**
906+
* Set the maximum number of query params
907+
*
908+
* @param maxQueryParams the new maximum
909+
* @return a reference to this, so the API can be used fluently
910+
*/
911+
public HttpServerOptions setMaxQueryParams(int maxQueryParams) {
912+
this.maxQueryParams = maxQueryParams;
913+
return this;
914+
}
915+
890916
/**
891917
* @return the initial HTTP/2 connection settings
892918
*/

vertx-core/src/main/java/io/vertx/core/http/impl/HttpServerConnectionHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public void handle(HttpServerConnection conn) {
103103
HttpServerOptions options = server.options;
104104
HttpServerRequestImpl request = new HttpServerRequestImpl(requestHandler, stream, stream.context(),
105105
options.isHandle100ContinueAutomatically(), options.getMaxFormAttributeSize(), options.getMaxFormFields(),
106-
options.getMaxFormBufferedBytes(), serverOrigin);
106+
options.getMaxFormBufferedBytes(), options.getMaxQueryParams(), serverOrigin);
107107
request.init();
108108
});
109109
}

vertx-core/src/main/java/io/vertx/core/http/impl/HttpServerRequestImpl.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public class HttpServerRequestImpl extends HttpServerRequestInternal {
5252
private final int maxFormAttributeSize;
5353
private final int maxFormFields;
5454
private final int maxFormBufferedBytes;
55+
private final int maxQueryParams;
5556
private final Handler<HttpServerRequest> handler;
5657

5758
// Accessed on context thread
@@ -79,6 +80,7 @@ public HttpServerRequestImpl(Handler<HttpServerRequest> handler,
7980
int maxFormAttributeSize,
8081
int maxFormFields,
8182
int maxFormBufferedBytes,
83+
int maxQueryParams,
8284
String serverOrigin) {
8385
this.handler = handler;
8486
this.context = context;
@@ -89,6 +91,7 @@ public HttpServerRequestImpl(Handler<HttpServerRequest> handler,
8991
this.handle100ContinueAutomatically = handle100ContinueAutomatically;
9092
this.maxFormAttributeSize = maxFormAttributeSize;
9193
this.maxFormFields = maxFormFields;
94+
this.maxQueryParams = maxQueryParams;
9295
this.maxFormBufferedBytes = maxFormBufferedBytes;
9396
}
9497

@@ -397,7 +400,7 @@ public String getParamsCharset() {
397400
public MultiMap params(boolean semicolonIsNormalChar) {
398401
synchronized (connection) {
399402
if (params == null || semicolonIsNormalChar != semicolonIsNormalCharInParams) {
400-
params = HttpUtils.params(uri(), paramsCharset, semicolonIsNormalChar);
403+
params = HttpUtils.params(uri(), paramsCharset, maxQueryParams, semicolonIsNormalChar);
401404
semicolonIsNormalCharInParams = semicolonIsNormalChar;
402405
}
403406
return params;

vertx-core/src/main/java/io/vertx/core/http/impl/HttpUtils.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,11 @@ public static String absoluteURI(String serverOrigin, HttpServerRequest req) {
343343
}
344344

345345
public static MultiMap params(String uri, Charset charset, boolean semicolonIsNormalChar) {
346-
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(uri, charset, true, 1024, semicolonIsNormalChar);
346+
return params(uri, charset, 1024, semicolonIsNormalChar);
347+
}
348+
349+
public static MultiMap params(String uri, Charset charset, int maxParams, boolean semicolonIsNormalChar) {
350+
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(uri, charset, true, maxParams, semicolonIsNormalChar);
347351
Map<String, List<String>> prms = queryStringDecoder.parameters();
348352
MultiMap params = MultiMap.caseInsensitiveMultiMap();
349353
if (!prms.isEmpty()) {

vertx-core/src/main/java/io/vertx/core/http/impl/http1x/Http1xServerRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ public String getParamsCharset() {
337337
@Override
338338
public MultiMap params(boolean semicolonIsNormalChar) {
339339
if (params == null || semicolonIsNormalChar != semicolonIsNormalCharInParams) {
340-
params = HttpUtils.params(uri(), paramsCharset, semicolonIsNormalChar);
340+
params = HttpUtils.params(uri(), paramsCharset, this.conn.options.getMaxQueryParams(), semicolonIsNormalChar);
341341
semicolonIsNormalCharInParams = semicolonIsNormalChar;
342342
}
343343
return params;

vertx-core/src/test/java/io/vertx/tests/http/Http1xTest.java

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,9 @@ public void testServerOptions() {
411411
assertEquals(256, options.getDecoderInitialBufferSize());
412412
assertIllegalArgumentException(() -> options.setDecoderInitialBufferSize(-1));
413413

414+
assertEquals(HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS, options.getMaxQueryParams());
415+
assertEquals(options, options.setMaxQueryParams(1025));
416+
assertEquals(1025, options.getMaxQueryParams());
414417
}
415418

416419
@Test
@@ -772,6 +775,7 @@ public void testCopyServerOptions() {
772775
boolean decompressionSupported = rand.nextBoolean();
773776
boolean acceptUnmaskedFrames = rand.nextBoolean();
774777
int decoderInitialBufferSize = TestUtils.randomPositiveInt();
778+
int maxQueryParams = TestUtils.randomPositiveInt();
775779

776780
options.setSendBufferSize(sendBufferSize);
777781
options.setReceiveBufferSize(receiverBufferSize);
@@ -803,6 +807,7 @@ public void testCopyServerOptions() {
803807
options.setDecompressionSupported(decompressionSupported);
804808
options.setAcceptUnmaskedFrames(acceptUnmaskedFrames);
805809
options.setDecoderInitialBufferSize(decoderInitialBufferSize);
810+
options.setMaxQueryParams(maxQueryParams);
806811

807812
HttpServerOptions copy = new HttpServerOptions(options);
808813
checkCopyHttpServerOptions(options, copy);
@@ -906,6 +911,7 @@ public void testServerOptionsJson() {
906911
boolean decompressionSupported = TestUtils.randomBoolean();
907912
boolean acceptUnmaskedFrames = TestUtils.randomBoolean();
908913
int decoderInitialBufferSize = TestUtils.randomPositiveInt();
914+
int maxQueryParams = TestUtils.randomPositiveInt();
909915

910916
JsonObject json = new JsonObject();
911917
json.put("sendBufferSize", sendBufferSize)
@@ -946,7 +952,8 @@ public void testServerOptionsJson() {
946952
.put("openSslSessionCacheEnabled", openSslSessionCacheEnabled)
947953
.put("decompressionSupported", decompressionSupported)
948954
.put("acceptUnmaskedFrames", acceptUnmaskedFrames)
949-
.put("decoderInitialBufferSize", decoderInitialBufferSize);
955+
.put("decoderInitialBufferSize", decoderInitialBufferSize)
956+
.put("maxQueryParams", maxQueryParams);
950957

951958
HttpServerOptions options = new HttpServerOptions(json);
952959
assertEquals(sendBufferSize, options.getSendBufferSize());
@@ -996,6 +1003,7 @@ public void testServerOptionsJson() {
9961003
assertEquals(decompressionSupported, options.isDecompressionSupported());
9971004
assertEquals(acceptUnmaskedFrames, options.isAcceptUnmaskedFrames());
9981005
assertEquals(decoderInitialBufferSize, options.getDecoderInitialBufferSize());
1006+
assertEquals(maxQueryParams, options.getMaxQueryParams());
9991007

10001008
// Test other keystore/truststore types
10011009
json.remove("keyStoreOptions");
@@ -2619,6 +2627,48 @@ private void testServerMaxHeaderSize(int maxHeaderSize) {
26192627
await();
26202628
}
26212629

2630+
@Test
2631+
public void testMaxQueryParams() {
2632+
testMaxQueryParams(HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS);
2633+
}
2634+
2635+
@Test
2636+
public void testMaxQueryParamsOption() {
2637+
testMaxQueryParams(HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS * 2);
2638+
}
2639+
2640+
private void testMaxQueryParams(Integer maxQueryParams) {
2641+
MultiMap params = TestUtils.randomMultiMap(HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS + 10);
2642+
String query = generateQueryString(params, ';');
2643+
2644+
vertx.createHttpServer(new HttpServerOptions().setMaxQueryParams(maxQueryParams).setMaxInitialLineLength(Integer.MAX_VALUE))
2645+
.requestHandler(req -> {
2646+
assertEquals(query, req.query());
2647+
if (maxQueryParams > HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS) {
2648+
assertEquals(params.size(), req.params().size());
2649+
} else {
2650+
assertEquals(HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS, req.params().size());
2651+
req.response().setStatusCode(414);
2652+
}
2653+
req.response().end();
2654+
}).listen(testAddress).onComplete(onSuccess(res -> {
2655+
client.close();
2656+
client = vertx.createHttpClient(new HttpClientOptions());
2657+
client
2658+
.request(new RequestOptions(requestOptions).setURI("some-uri/?" + query))
2659+
.compose(req -> req.send().compose(resp -> {
2660+
if (maxQueryParams > HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS) {
2661+
assertEquals(200, resp.statusCode());
2662+
} else {
2663+
assertEquals(414, resp.statusCode());
2664+
}
2665+
return resp.end();
2666+
}))
2667+
.onComplete(onSuccess(v -> testComplete()));
2668+
}));
2669+
await();
2670+
}
2671+
26222672
@Test
26232673
public void testPipelinedInvalidHttpResponse() {
26242674

0 commit comments

Comments
 (0)