Skip to content

RequestHandler parses JSON-RPC body twice for authorized requests #33

@MastaP

Description

@MastaP

Problem

For authorized JSON-RPC requests, RequestHandler parses the request body twice:

  1. extractJsonRpcMethodFromBody (called from handle(), RequestHandler.java:189) — streaming parse via Jackson JsonParser to pull out only the method field, used to decide auth/rate-limiting policy.
  2. parseRequestBodyAsJsonForRouting (called from determineTargetUrl, RequestHandler.java:501) — full objectMapper.readTree(...) to extract stateId/shardId.

The streaming parse is cheap and short-circuits early, so for rejected requests (auth/size failures) the redundancy doesn't matter — that path never runs the second parse. For authorized requests it does, and we pay both costs.

Why this wasn't fixed in #32

PR #32 adds Prometheus instrumentation; this is a pre-existing issue flagged by review there. Out of scope for that PR.

Suggested fix

Parse the body into a JsonNode once after the size check passes; pass the parsed tree (or null for non-JSON bodies) through handleRequestAsyncproxyRequestdetermineTargetUrl. extractJsonRpcMethodFromBody becomes a tree lookup instead of a streaming parse.

Trade-off: streaming parse currently allocates very little when the method field appears early in the body (which is the common case for our clients). Switching to readTree allocates the whole tree even on the rejection path, where today we don't. So the right fix is conditional — only parse the tree once we know we'll need routing too. Concretely:

  • Keep the streaming extractJsonRpcMethodFromBody.
  • Add a lazy JsonNode holder built on first call inside determineTargetUrl.
  • For methods whose routing comes from headers (X-State-ID) or cookies, never parse the tree at all.

Acceptance criteria

  • For authorized JSON-RPC requests with body-derived routing params, the body is parsed once.
  • For requests rejected before the proxy step (auth fail / size fail / 405 etc.), allocation profile is no worse than today.
  • No regression in ProxyServerIntegrationTest, RateLimitingTest, ShardRoutingIntegrationTest, BftShardRoutingIntegrationTest.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions