Skip to content

Commit 498c9da

Browse files
committed
fix the bug of only one erro is return is the n-th request is overflow
1 parent e6eca1c commit 498c9da

2 files changed

Lines changed: 45 additions & 11 deletions

File tree

framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcServlet.java

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,24 @@ private void handleBatch(HttpServletResponse resp, JsonNode rootNode, int maxRes
154154

155155
ArrayNode batchResult = MAPPER.createArrayNode();
156156
int accumulatedSize = 2; // "[]"
157+
boolean overflow = false;
157158

158159
for (int i = 0; i < rootNode.size(); i++) {
160+
JsonNode subRequest = rootNode.get(i);
161+
162+
if (overflow) {
163+
// Notifications (no "id") do not get a response even on overflow.
164+
if (subRequest.has("id")) {
165+
batchResult.add(buildErrorNode(JsonRpcError.RESPONSE_TOO_LARGE,
166+
"Response exceeds the limit of " + maxResponseSize + " bytes",
167+
subRequest.get("id")));
168+
}
169+
continue;
170+
}
171+
159172
byte[] subBody;
160173
try {
161-
subBody = MAPPER.writeValueAsBytes(rootNode.get(i));
174+
subBody = MAPPER.writeValueAsBytes(subRequest);
162175
} catch (JsonProcessingException e) {
163176
writeJsonRpcError(resp, JsonRpcError.INTERNAL_ERROR, "Internal error", null, true);
164177
return;
@@ -178,12 +191,14 @@ private void handleBatch(HttpServletResponse resp, JsonNode rootNode, int maxRes
178191
continue; // notification — no response
179192
}
180193

181-
// comma separator between array elements
194+
// comma(,) separator between array elements
182195
int addition = responseBytes.length + (!batchResult.isEmpty() ? 1 : 0);
183196
if (maxResponseSize > 0 && accumulatedSize + addition > maxResponseSize) {
184-
writeJsonRpcError(resp, JsonRpcError.RESPONSE_TOO_LARGE,
185-
"Response exceeds the limit of " + maxResponseSize + " bytes", null, true);
186-
return;
197+
overflow = true;
198+
batchResult.add(buildErrorNode(JsonRpcError.RESPONSE_TOO_LARGE,
199+
"Response exceeds the limit of " + maxResponseSize + " bytes",
200+
subRequest.get("id")));
201+
continue;
187202
}
188203
accumulatedSize += addition;
189204

@@ -197,6 +212,13 @@ private void handleBatch(HttpServletResponse resp, JsonNode rootNode, int maxRes
197212
batchResult.add(responseNode);
198213
}
199214

215+
// JSON-RPC 2.0 §6: MUST NOT return an empty Array when there are no response objects.
216+
if (batchResult.isEmpty()) {
217+
resp.setStatus(HttpServletResponse.SC_OK);
218+
resp.setContentLength(0);
219+
return;
220+
}
221+
200222
byte[] finalBytes = MAPPER.writeValueAsBytes(batchResult);
201223
resp.setContentType("application/json; charset=utf-8");
202224
resp.setStatus(HttpServletResponse.SC_OK);
@@ -215,8 +237,7 @@ private byte[] readBody(InputStream in) throws IOException {
215237
return buffer.toByteArray();
216238
}
217239

218-
private void writeJsonRpcError(HttpServletResponse resp, JsonRpcError error, String message,
219-
JsonNode id, boolean isBatch) throws IOException {
240+
private ObjectNode buildErrorNode(JsonRpcError error, String message, JsonNode id) {
220241
ObjectNode errorObj = MAPPER.createObjectNode();
221242
errorObj.put("jsonrpc", "2.0");
222243
ObjectNode errNode = errorObj.putObject("error");
@@ -227,6 +248,12 @@ private void writeJsonRpcError(HttpServletResponse resp, JsonRpcError error, Str
227248
} else {
228249
errorObj.putNull("id");
229250
}
251+
return errorObj;
252+
}
253+
254+
private void writeJsonRpcError(HttpServletResponse resp, JsonRpcError error, String message,
255+
JsonNode id, boolean isBatch) throws IOException {
256+
ObjectNode errorObj = buildErrorNode(error, message, id);
230257
byte[] bytes;
231258
if (isBatch) {
232259
ArrayNode arr = MAPPER.createArrayNode();

framework/src/test/java/org/tron/core/services/jsonrpc/JsonRpcServletTest.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,9 @@ public void batchLimitDisabled_largeBatchAllowed() throws Exception {
133133
sb.append("]");
134134
MockHttpServletResponse resp = doPost(sb.toString());
135135
assertEquals(200, resp.getStatus());
136-
JsonNode body = MAPPER.readTree(resp.getContentAsByteArray());
137-
assertTrue("response must be a JSON array", body.isArray());
138-
assertEquals("all notifications produce no response entries", 0, body.size());
136+
assertEquals("all-notification batch must return empty body per JSON-RPC 2.0 §6",
137+
0, resp.getContentLength());
138+
assertEquals("", resp.getContentAsString());
139139
}
140140

141141
// --- rpcServer.handle exceptions ---
@@ -218,7 +218,14 @@ public void batchShortCircuitsOnOverflow() throws Exception {
218218
assertEquals(200, resp.getStatus());
219219
JsonNode body = MAPPER.readTree(resp.getContentAsString());
220220
assertTrue("overflow response must be an array", body.isArray());
221-
assertEquals(-32003, body.get(0).get("error").get("code").asInt());
221+
// Geth-compatible: previous successes are preserved; overflow item and remaining
222+
// unexecuted items each get a -32003 error with their original id.
223+
assertEquals(3, body.size());
224+
assertEquals("ok", body.get(0).get("result").asText());
225+
assertEquals(-32003, body.get(1).get("error").get("code").asInt());
226+
assertEquals(2, body.get(1).get("id").asInt());
227+
assertEquals(-32003, body.get(2).get("error").get("code").asInt());
228+
assertEquals(3, body.get(2).get("id").asInt());
222229
assertEquals("third sub-request must not be executed after overflow", 2, callCount[0]);
223230
}
224231

0 commit comments

Comments
 (0)