Skip to content

Conversation

@jasuwienas
Copy link
Contributor

@jasuwienas jasuwienas commented Nov 26, 2025

Description

Compliance layer checking if the api response format is correct - fixing it when needed.

Related issue(s)

Fixes #4630

Testing Guide

  1. Run tests
  2. Check if pass

Changes from original design (optional)

Additional work needed (optional)

N/A

Checklist

  • I've assigned an assignee to this PR and related issue(s) (if applicable)
  • I've assigned a label to this PR and related issue(s) (if applicable)
  • I've assigned a milestone to this PR and related issue(s) (if applicable)
  • I've updated documentation (code comments, README, etc. if applicable)
  • I've done sufficient testing (unit, integration, etc.)

@jasuwienas jasuwienas changed the title 4630 review the 200 and 400 http code feat: review the 200 and 400 http code Nov 26, 2025
@jasuwienas
Copy link
Contributor Author

ID Acceptance Criterion Verification Method
AC01.A Malformed HTTP requests by method/body: using the wrong HTTP method (GET/PUT instead of POST) or sending no body at all MUST return HTTP 400 when VALID_JSON_RPC_HTTP_REQUESTS_STATUS_CODE = false. When the flag is true, these still return HTTP 200 but with a JSON-RPC error. - VALID_JSON_RPC_HTTP_REQUESTS_STATUS_CODE = false:
curl -X GET … with/without body -> 400.
curl -X PUT … with no/empty body -> 400.
- VALID_JSON_RPC_HTTP_REQUESTS_STATUS_CODE = true: same requests -> 200 + JSON-RPC error in body.
AC01.B Malformed / missing Content-Type: if the request body is valid JSON, it MUST still be parsed and processed as JSON-RPC even when Content-Type is missing or incorrect (treated as if application/json was sent). HTTP status still follows AC07/AC08 rules. - curl -X POST … without Content-Type and with valid JSON body -> processed and returns normal JSON-RPC response.
- curl -X POST … -H "Content-Type: application/not-json" with valid JSON body -> still processed and returns JSON-RPC response (like Infura/Alchemy).
AC02 Valid HTTP but invalid JSON payload returns HTTP 400 + JSON-RPC error code -32700 (Parse error) when VALID_JSON_RPC_HTTP_REQUESTS_STATUS_CODE = false; when true, still 200 but with -32700 error in the JSON-RPC body. Send a broken JSON payload, e.g. {"jsonrpc":"2.0", ->
- Flag false -> 400 + body with {"code": -32700, ...}.
- Flag true -> 200 + same error object.
AC03 Valid JSON but not a valid JSON-RPC 2.0 object (missing jsonrpc/method/id, wrong types) returns HTTP 400 + code -32600 (or 200 with -32600 when flag is true). Send {"id":1} or {"jsonrpc":"2.0"} ->
- Flag false -> 400 + {"code": -32600, ...}.
- Flag true -> 200 + same error.
AC04 Unknown/unsupported method returns JSON-RPC error -32601 (Method not found), with HTTP 400 or 200 depending on the flag. Call e.g. eth_doesNotExist ->
- Flag false -> 400 + {"code": -32601, ...}.
- Flag true -> 200 + same error.
AC05 Invalid parameters (wrong type, missing param, out-of-range, etc.) return JSON-RPC error -32602 (Invalid params), with HTTP 400 or 200 depending on the flag. Call eth_getBalance with wrong param type or missing param ->
- Flag false -> 400 + {"code": -32602, ...}.
- Flag true -> 200 + same error.
AC06 Any limit exceeded (payload size below 413 threshold, eth_getLogs block range, number of addresses, etc.) returns a JSON-RPC error (e.g. -32521, -32500, or custom) with HTTP 400 or 200 depending on the flag. Huge eth_getLogs, huge ranges, too many items, etc. ->
- Flag false -> 400 + clear JSON-RPC error.
- Flag true -> 200 + same error.
AC07 When VALID_JSON_RPC_HTTP_REQUESTS_STATUS_CODE = false, only fully valid and successful JSON-RPC requests return HTTP 200 with result; all JSON-RPC client errors (AC01–AC06) use HTTP 400. Start without the env var (or set to false).
- Correct eth_blockNumber -> 200 + "result":"0x...".
- Trigger AC01–AC06 cases -> all return 400 with appropriate JSON-RPC error in body.
AC08 When VALID_JSON_RPC_HTTP_REQUESTS_STATUS_CODE = true, all syntactically valid JSON-RPC payloads return HTTP 200, even if HTTP method is GET/PUT, Content-Type is missing/wrong, or body is empty. Errors are expressed only via JSON-RPC error objects (AC01–AC06, AC15). Start with env var set to true.
Repeat AC01.A–AC06 tests:
- Wrong method, no body, bad JSON, invalid RPC, etc. -> 200 in all those cases, with proper JSON-RPC error objects (-32700, -32600, -32601, -32602, custom, etc.).
AC09 The VALID_JSON_RPC_HTTP_REQUESTS_STATUS_CODE flag is read at startup, and toggling it does not require code changes, only configuration / restart. Start node with flag off -> observe AC07 behavior; restart with flag on -> observe AC08 behavior.
AC10 Every response (200, 400, 429, etc.) contains a valid JSON-RPC 2.0 body with matching id, "jsonrpc": "2.0", and either result or error, except AC14 where the body must be empty. Inspect responses for all test cases:
- Body is always valid JSON-RPC with matching id and "jsonrpc":"2.0", and result or error.
- For AC14, confirm no body (empty response).
AC11 Error messages are clear and actionable (e.g., “Invalid param 1: expected Quantity”, “Request exceeds max block range of 5000”). Manual or automated inspection of error.message fields across typical failure cases: messages should be specific, not generic.
AC12 No JSON-RPC–level client error ever returns HTTP 500; 500 is reserved only for real unhandled crashes/bugs. Trigger various known client errors (invalid params, methods, malformed requests) -> they never return 500 (only 400 or 200 depending on the flag).
AC13 Rate-limiting errors (if implemented) return HTTP 429 with a clear, actionable message and a JSON-RPC error object. Trigger rate limiting (high QPS, etc.) -> 429 plus JSON body with JSON-RPC error and human-readable message like “Rate limit exceeded”.
AC14 Too big request body (exceeding maximum payload size) returns HTTP 413 with no response body. This matches current implementation and is now codified. Send a request with a very large body (above configured max payload size) -> 413 and empty body (no JSON, no HTML).
AC15 Too many requests in a batch should still return a JSON-RPC batch array of the same length, with each element containing error code -32005 (“batch size exceeds the per method rate limit”), as long as AC14 (413) is not triggered by raw size. Send a batch request with many items (e.g. 5000) that exceeds logical/batch limits but not raw payload size -> response is an array of the same length, each entry containing an error object with code: -32005 (like Infura’s example).

Comparing responses between networks:

Unified JSON-RPC Negative Test Comparison Table

Includes: QuickNode, Infura, Chainstack, Alchemy, Geth, Besu

Provider Wrong Method (PUT) Wrong Content-Type (none) Wrong Content-Type (text/plain) Malformed Body (non-JSON) Missing ID Wrong JSON-RPC Version Large Batch (200)
QuickNode 403 (empty body), rejects PUT. 200, returns valid result. 200, returns valid result. 400, parse error failed to parse request. 200, id=null, still returns result. 200, ignores version mismatch and returns result. 200, mix of results plus many -32007 “15/second request limit reached” errors. Array of size eq to number of requests.
Infura 200, error -32603 Internal error (PUT accepted but fails internally). 200, returns result. 200, returns result. 200, error -32700 Invalid JSON. 200, error -32603 Internal error. 200, returns result despite version mismatch. 200, all entries error -32005 batch size exceeds the per method rate limit (limit 500). Array of size eq to number of requests.
Chainstack 405 (empty body). 200, returns result. 200, returns result. 400, error -32600 Invalid json request. 200, returns result with id=0. 200, returns result. 200, many entries error -32005 You've exceeded the RPS limit with try_again_in hints. Array of size eq to number of requests.
Alchemy 404 (empty body). 200, returns result. 200, returns result. 400, parse error -32700. 200, id=null with result. 200, returns result despite version mismatch. 200, all entries error -32600 “maximum batch request size is 1000”. Array of size eq to number of requests.
Geth 405, rejects PUT. 415, only application/json supported. 415, only application/json supported. 200, JSON error -32700 parse error. 200, empty body (Geth returns no result when ID missing). 200, JSON error -32600 invalid request. 200, error -32600 batch too large. Array with 1 element with id of the first request
Besu 405, rejects PUT. 200, returns result 0x0. 200, returns result 0x0. 400, JSON error -32700 Parse error. 200, empty body (no result). 200, returns result 0x0. 200, error -32005 Number of requests exceeds max batch size. One object with id null

@jasuwienas jasuwienas marked this pull request as ready for review December 1, 2025 13:08
@jasuwienas jasuwienas requested review from a team as code owners December 1, 2025 13:08
@jasuwienas
Copy link
Contributor Author

I should gain access to run GitHub Actions soon. I’ll remove the draft status afterward. It would be good to run them just to make sure all the tests still work correctly with the default configuration.

@jasuwienas jasuwienas marked this pull request as draft December 1, 2025 13:12
@jasuwienas jasuwienas force-pushed the 4630-review-the-200-and-400-http-code branch from 4a8f0d9 to 49fe5df Compare December 1, 2025 13:47
@jasuwienas
Copy link
Contributor Author

Tests were prepared in accordance with the AC described above.

@jasuwienas jasuwienas marked this pull request as ready for review December 2, 2025 13:53
@jasuwienas jasuwienas added the enhancement New feature or request label Dec 3, 2025
@jasuwienas jasuwienas added this to the 0.74.0 milestone Dec 3, 2025
@jasuwienas jasuwienas force-pushed the 4630-review-the-200-and-400-http-code branch 2 times, most recently from 41292bc to 25b5953 Compare December 5, 2025 08:46
@codecov
Copy link

codecov bot commented Dec 5, 2025

Codecov Report

❌ Patch coverage is 81.48148% with 15 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
packages/server/src/compliance.ts 80.00% 12 Missing and 1 partial ⚠️
packages/server/src/server.ts 50.00% 2 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (2e9648a) and HEAD (96903f1). Click for more details.

HEAD has 19 uploads less than BASE
Flag BASE (2e9648a) HEAD (96903f1)
ws-server 1 0
19 1
@@            Coverage Diff             @@
##             main    #4650      +/-   ##
==========================================
- Coverage   95.47%   88.44%   -7.04%     
==========================================
  Files         129      130       +1     
  Lines       20928    21003      +75     
  Branches     1793     1593     -200     
==========================================
- Hits        19982    18576    -1406     
- Misses        926     2392    +1466     
- Partials       20       35      +15     
Flag Coverage Δ
config-service 98.83% <100.00%> (+<0.01%) ⬆️
relay 90.88% <ø> (ø)
server 88.21% <80.26%> (-0.79%) ⬇️
ws-server ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...ckages/config-service/src/services/globalConfig.ts 100.00% <100.00%> (ø)
packages/server/src/koaJsonRpc/index.ts 90.33% <100.00%> (-1.37%) ⬇️
packages/server/src/server.ts 87.42% <50.00%> (-0.51%) ⬇️
packages/server/src/compliance.ts 80.00% <80.00%> (ø)

... and 41 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jasuwienas jasuwienas requested a review from a team as a code owner December 5, 2025 12:24
@jasuwienas jasuwienas force-pushed the 4630-review-the-200-and-400-http-code branch from 52ff9f7 to c096109 Compare December 5, 2025 13:46
@jasuwienas
Copy link
Contributor Author

jasuwienas commented Dec 5, 2025

AC08 - we will go for 400 when we do validation

BATCH 200, array, number of elements in req = number of elements in resp
405 for wrong method

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Review the 200 and 400 http error codes and make them configurable

1 participant