Skip to content

Commit 279d19b

Browse files
authored
feat(http): add SizeLimitHandler to enforce request body size limit (#6658)
1 parent 328480f commit 279d19b

18 files changed

Lines changed: 701 additions & 7 deletions

File tree

common/src/main/java/org/tron/common/parameter/CommonParameter.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,19 @@ public class CommonParameter {
228228
@Getter
229229
@Setter
230230
public long maxConnectionAgeInMillis;
231+
// Refers to RPC (gRPC) max message size; see httpMaxMessageSize / jsonRpcMaxMessageSize
232+
// below for the HTTP / JSON-RPC counterparts.
231233
@Getter
232234
@Setter
233235
public int maxMessageSize;
234236
@Getter
235237
@Setter
238+
public long httpMaxMessageSize;
239+
@Getter
240+
@Setter
241+
public long jsonRpcMaxMessageSize;
242+
@Getter
243+
@Setter
236244
public int maxHeaderListSize;
237245
@Getter
238246
@Setter

common/src/main/java/org/tron/core/config/args/NodeConfig.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
package org.tron.core.config.args;
22

33
import static org.tron.core.config.Parameter.ChainConstant.MAX_ACTIVE_WITNESS_NUM;
4+
import static org.tron.core.exception.TronError.ErrCode.PARAMETER_INIT;
45

56
import com.typesafe.config.Config;
67
import com.typesafe.config.ConfigBeanFactory;
78
import com.typesafe.config.ConfigFactory;
9+
import com.typesafe.config.ConfigValueFactory;
810
import java.util.ArrayList;
911
import java.util.List;
1012
import lombok.Getter;
1113
import lombok.Setter;
1214
import lombok.extern.slf4j.Slf4j;
15+
import org.tron.core.exception.TronError;
1316

1417
// Node configuration bean for the "node" section of config.conf.
1518
// ConfigBeanFactory auto-binds all fields including sub-beans, dot-notation keys,
@@ -198,6 +201,7 @@ public static class HttpConfig {
198201
private int fullNodePort = 8090;
199202
private boolean solidityEnable = true;
200203
private int solidityPort = 8091;
204+
private long maxMessageSize = 4194304;
201205
// PBFT fields — handled manually (same naming issue as CommitteeConfig)
202206
// Default must match CommonParameter.pBFTHttpEnable = true
203207
@Getter(lombok.AccessLevel.NONE)
@@ -303,6 +307,7 @@ public void setHttpPBFTPort(int v) {
303307
private int maxBlockRange = 5000;
304308
private int maxSubTopics = 1000;
305309
private int maxBlockFilterNum = 50000;
310+
private long maxMessageSize = 4194304;
306311
}
307312

308313
@Getter
@@ -360,7 +365,11 @@ public static class DnsConfig {
360365
* since ConfigBeanFactory expects typed bean lists, not string lists.
361366
*/
362367
public static NodeConfig fromConfig(Config config) {
363-
Config section = config.getConfig("node");
368+
// Normalize human-readable size values (e.g. "4m") to numeric bytes so
369+
// ConfigBeanFactory's primitive int/long binding succeeds; same step
370+
// enforces non-negative and <= Integer.MAX_VALUE before bean creation
371+
// so failures point at the user-facing config path.
372+
Config section = normalizeMaxMessageSizes(config).getConfig("node");
364373

365374
// Auto-bind all fields and sub-beans. ConfigBeanFactory fails fast with a
366375
// descriptive path on any `= null` value — external configs that use the
@@ -500,4 +509,34 @@ private static String getString(Config config, String path, String defaultValue)
500509
return config.hasPath(path) ? config.getString(path) : defaultValue;
501510
}
502511

512+
// Pre-normalize size paths so ConfigBeanFactory's primitive int/long binding succeeds
513+
// for human-readable values like "4m" / "128MB". For each maxMessageSize key, parse
514+
// via getMemorySize, validate non-negative and <= Integer.MAX_VALUE, and write the
515+
// numeric byte value back into the Config tree. Validation errors propagate before
516+
// bean creation so the failure points at the user-facing config path.
517+
private static Config normalizeMaxMessageSizes(Config config) {
518+
String[] paths = {
519+
"node.rpc.maxMessageSize",
520+
"node.http.maxMessageSize",
521+
"node.jsonrpc.maxMessageSize"
522+
};
523+
Config result = config;
524+
for (String path : paths) {
525+
if (config.hasPath(path)) {
526+
long bytes = parseMaxMessageSize(config, path);
527+
result = result.withValue(path, ConfigValueFactory.fromAnyRef(bytes));
528+
}
529+
}
530+
return result;
531+
}
532+
533+
private static long parseMaxMessageSize(Config config, String key) {
534+
long value = config.getMemorySize(key).toBytes();
535+
if (value < 0 || value > Integer.MAX_VALUE) {
536+
throw new TronError(key + " must be non-negative and <= "
537+
+ Integer.MAX_VALUE + ", got: " + value, PARAMETER_INIT);
538+
}
539+
return value;
540+
}
541+
503542
}

common/src/main/resources/reference.conf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ node {
271271
solidityPort = 8091
272272
PBFTEnable = true
273273
PBFTPort = 8092
274+
275+
# Maximum HTTP request body size, default 4MB. Independent from rpc.maxMessageSize.
276+
maxMessageSize = 4M
274277
}
275278

276279
rpc {
@@ -402,6 +405,9 @@ node {
402405

403406
# Maximum number for blockFilter
404407
maxBlockFilterNum = 50000
408+
409+
# Maximum JSON-RPC request body size, default 4MB. Independent from rpc.maxMessageSize.
410+
maxMessageSize = 4M
405411
}
406412

407413
# Disabled API list (works for http, rpc and pbft, not jsonrpc). Case insensitive.

framework/src/main/java/org/tron/common/application/HttpService.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515

1616
package org.tron.common.application;
1717

18+
import com.google.common.annotations.VisibleForTesting;
1819
import java.util.concurrent.CompletableFuture;
1920
import lombok.extern.slf4j.Slf4j;
2021
import org.eclipse.jetty.server.ConnectionLimit;
2122
import org.eclipse.jetty.server.Server;
23+
import org.eclipse.jetty.server.handler.SizeLimitHandler;
2224
import org.eclipse.jetty.servlet.ServletContextHandler;
2325
import org.tron.core.config.args.Args;
2426

@@ -29,6 +31,18 @@ public abstract class HttpService extends AbstractService {
2931

3032
protected String contextPath;
3133

34+
protected long maxRequestSize = 4 * 1024 * 1024; // 4MB
35+
36+
@VisibleForTesting
37+
public long getMaxRequestSize() {
38+
return this.maxRequestSize;
39+
}
40+
41+
@VisibleForTesting
42+
public void setMaxRequestSize(long maxRequestSize) {
43+
this.maxRequestSize = maxRequestSize;
44+
}
45+
3246
@Override
3347
public void innerStart() throws Exception {
3448
if (this.apiServer != null) {
@@ -63,7 +77,9 @@ protected void initServer() {
6377
protected ServletContextHandler initContextHandler() {
6478
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
6579
context.setContextPath(this.contextPath);
66-
this.apiServer.setHandler(context);
80+
SizeLimitHandler sizeLimitHandler = new SizeLimitHandler(this.maxRequestSize, -1);
81+
sizeLimitHandler.setHandler(context);
82+
this.apiServer.setHandler(sizeLimitHandler);
6783
return context;
6884
}
6985

framework/src/main/java/org/tron/core/config/args/Args.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ private static void applyNodeConfig(NodeConfig nc) {
573573
PARAMETER.fullNodeHttpPort = http.getFullNodePort();
574574
PARAMETER.solidityHttpPort = http.getSolidityPort();
575575
PARAMETER.pBFTHttpPort = http.getPBFTPort();
576+
PARAMETER.httpMaxMessageSize = http.getMaxMessageSize();
576577

577578
// ---- JSON-RPC sub-bean ----
578579
NodeConfig.JsonRpcConfig jsonrpc = nc.getJsonrpc();
@@ -585,6 +586,7 @@ private static void applyNodeConfig(NodeConfig nc) {
585586
PARAMETER.jsonRpcMaxBlockRange = jsonrpc.getMaxBlockRange();
586587
PARAMETER.jsonRpcMaxSubTopics = jsonrpc.getMaxSubTopics();
587588
PARAMETER.jsonRpcMaxBlockFilterNum = jsonrpc.getMaxBlockFilterNum();
589+
PARAMETER.jsonRpcMaxMessageSize = jsonrpc.getMaxMessageSize();
588590

589591
// ---- P2P sub-bean ----
590592
PARAMETER.nodeP2pVersion = nc.getP2p().getVersion();

framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ public FullNodeHttpApiService() {
297297
port = Args.getInstance().getFullNodeHttpPort();
298298
enable = isFullNode() && Args.getInstance().isFullNodeHttpEnable();
299299
contextPath = "/";
300+
maxRequestSize = Args.getInstance().getHttpMaxMessageSize();
300301
}
301302

302303
@Override

framework/src/main/java/org/tron/core/services/http/Util.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,12 @@ public static Transaction packTransaction(String strTransaction, boolean selfTyp
356356
}
357357
}
358358

359+
@Deprecated
359360
public static void checkBodySize(String body) throws Exception {
360361
CommonParameter parameter = Args.getInstance();
361-
if (body.getBytes().length > parameter.getMaxMessageSize()) {
362-
throw new Exception("body size is too big, the limit is " + parameter.getMaxMessageSize());
362+
if (body.getBytes().length > parameter.getHttpMaxMessageSize()) {
363+
throw new Exception("body size is too big, the limit is "
364+
+ parameter.getHttpMaxMessageSize());
363365
}
364366
}
365367

framework/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ public SolidityNodeHttpApiService() {
170170
port = Args.getInstance().getSolidityHttpPort();
171171
enable = !isFullNode() && Args.getInstance().isSolidityNodeHttpEnable();
172172
contextPath = "/";
173+
maxRequestSize = Args.getInstance().getHttpMaxMessageSize();
173174
}
174175

175176
@Override

framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnPBFT/JsonRpcServiceOnPBFT.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public JsonRpcServiceOnPBFT() {
1919
port = Args.getInstance().getJsonRpcHttpPBFTPort();
2020
enable = isFullNode() && Args.getInstance().isJsonRpcHttpPBFTNodeEnable();
2121
contextPath = "/";
22+
maxRequestSize = Args.getInstance().getJsonRpcMaxMessageSize();
2223
}
2324

2425
@Override

framework/src/main/java/org/tron/core/services/interfaceJsonRpcOnSolidity/JsonRpcServiceOnSolidity.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public JsonRpcServiceOnSolidity() {
1919
port = Args.getInstance().getJsonRpcHttpSolidityPort();
2020
enable = isFullNode() && Args.getInstance().isJsonRpcHttpSolidityNodeEnable();
2121
contextPath = "/";
22+
maxRequestSize = Args.getInstance().getJsonRpcMaxMessageSize();
2223
}
2324

2425
@Override

0 commit comments

Comments
 (0)