Skip to content

Commit 3b96aa0

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

File tree

8 files changed

+94
-6
lines changed

8 files changed

+94
-6
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: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
import java.util.concurrent.atomic.AtomicInteger;
5353
import java.util.concurrent.atomic.AtomicReference;
5454
import java.util.function.*;
55-
import java.util.stream.Collector;
5655
import java.util.stream.Collectors;
5756
import java.util.stream.IntStream;
5857
import java.util.stream.Stream;
@@ -411,6 +410,9 @@ public void testServerOptions() {
411410
assertEquals(256, options.getDecoderInitialBufferSize());
412411
assertIllegalArgumentException(() -> options.setDecoderInitialBufferSize(-1));
413412

413+
assertEquals(HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS, options.getMaxQueryParams());
414+
assertEquals(options, options.setMaxQueryParams(1025));
415+
assertEquals(1025, options.getMaxQueryParams());
414416
}
415417

416418
@Test
@@ -772,6 +774,7 @@ public void testCopyServerOptions() {
772774
boolean decompressionSupported = rand.nextBoolean();
773775
boolean acceptUnmaskedFrames = rand.nextBoolean();
774776
int decoderInitialBufferSize = TestUtils.randomPositiveInt();
777+
int maxQueryParams = TestUtils.randomPositiveInt();
775778

776779
options.setSendBufferSize(sendBufferSize);
777780
options.setReceiveBufferSize(receiverBufferSize);
@@ -803,6 +806,7 @@ public void testCopyServerOptions() {
803806
options.setDecompressionSupported(decompressionSupported);
804807
options.setAcceptUnmaskedFrames(acceptUnmaskedFrames);
805808
options.setDecoderInitialBufferSize(decoderInitialBufferSize);
809+
options.setMaxQueryParams(maxQueryParams);
806810

807811
HttpServerOptions copy = new HttpServerOptions(options);
808812
checkCopyHttpServerOptions(options, copy);
@@ -906,6 +910,7 @@ public void testServerOptionsJson() {
906910
boolean decompressionSupported = TestUtils.randomBoolean();
907911
boolean acceptUnmaskedFrames = TestUtils.randomBoolean();
908912
int decoderInitialBufferSize = TestUtils.randomPositiveInt();
913+
int maxQueryParams = TestUtils.randomPositiveInt();
909914

910915
JsonObject json = new JsonObject();
911916
json.put("sendBufferSize", sendBufferSize)
@@ -946,7 +951,8 @@ public void testServerOptionsJson() {
946951
.put("openSslSessionCacheEnabled", openSslSessionCacheEnabled)
947952
.put("decompressionSupported", decompressionSupported)
948953
.put("acceptUnmaskedFrames", acceptUnmaskedFrames)
949-
.put("decoderInitialBufferSize", decoderInitialBufferSize);
954+
.put("decoderInitialBufferSize", decoderInitialBufferSize)
955+
.put("maxQueryParams", maxQueryParams);
950956

951957
HttpServerOptions options = new HttpServerOptions(json);
952958
assertEquals(sendBufferSize, options.getSendBufferSize());
@@ -996,6 +1002,7 @@ public void testServerOptionsJson() {
9961002
assertEquals(decompressionSupported, options.isDecompressionSupported());
9971003
assertEquals(acceptUnmaskedFrames, options.isAcceptUnmaskedFrames());
9981004
assertEquals(decoderInitialBufferSize, options.getDecoderInitialBufferSize());
1005+
assertEquals(maxQueryParams, options.getMaxQueryParams());
9991006

10001007
// Test other keystore/truststore types
10011008
json.remove("keyStoreOptions");

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,6 +2346,48 @@ public void test1xxRemovesTransferEncodingHeader() throws Exception {
23462346
assertNull(respHeaders.get("transfer-encoding"));
23472347
}
23482348

2349+
@Test
2350+
public void testMaxQueryParams() {
2351+
testMaxQueryParams(HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS);
2352+
}
2353+
2354+
@Test
2355+
public void testMaxQueryParamsOption() {
2356+
testMaxQueryParams(HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS * 2);
2357+
}
2358+
2359+
private void testMaxQueryParams(Integer maxQueryParams) {
2360+
MultiMap params = TestUtils.randomMultiMap(HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS + 10);
2361+
String query = generateQueryString(params, ';');
2362+
2363+
vertx.createHttpServer(new HttpServerOptions().setMaxQueryParams(maxQueryParams).setMaxInitialLineLength(Integer.MAX_VALUE))
2364+
.requestHandler(req -> {
2365+
assertEquals(query, req.query());
2366+
if (maxQueryParams > HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS) {
2367+
assertEquals(params.size(), req.params().size());
2368+
} else {
2369+
assertEquals(HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS, req.params().size());
2370+
req.response().setStatusCode(414);
2371+
}
2372+
req.response().end();
2373+
}).listen(testAddress).onComplete(onSuccess(res -> {
2374+
client.close();
2375+
client = vertx.createHttpClient(new HttpClientOptions());
2376+
client
2377+
.request(new RequestOptions(requestOptions).setURI("some-uri/?" + query))
2378+
.compose(req -> req.send().compose(resp -> {
2379+
if (maxQueryParams > HttpServerOptions.DEFAULT_MAX_QUERY_PARAMS) {
2380+
assertEquals(200, resp.statusCode());
2381+
} else {
2382+
assertEquals(414, resp.statusCode());
2383+
}
2384+
return resp.end();
2385+
}))
2386+
.onComplete(onSuccess(v -> testComplete()));
2387+
}));
2388+
await();
2389+
}
2390+
23492391
protected MultiMap checkEmptyHttpResponse(HttpMethod method, int sc, MultiMap reqHeaders) throws Exception {
23502392
server.requestHandler(req -> {
23512393
HttpServerResponse resp = req.response();

0 commit comments

Comments
 (0)