pub fn parse_request(
body: Value,
max_calls: usize,
) -> Result<JmapRequest, JmapError>Expand description
Parse and validate a JMAP request from a raw JSON value.
Validates:
- The body deserializes as a
JmapRequest. - The number of method calls does not exceed
max_calls(RFC 8620 §3.3).
An empty using array is not rejected here. Per the jmap-test-suite
conformance ruling (Q4 / error-empty-using), the server must process the
request and return unknownMethod for every call — not a 400-level
notRequest. Capability URI validation is the caller’s responsibility;
call check_known_capabilities immediately after this function and map
any Err to an HTTP 400 response.
§Caller responsibility: notJSON
This function takes a pre-parsed serde_json::Value, not raw bytes. The
caller is responsible for the initial JSON parse of the HTTP request body.
If that parse fails (the body is not valid JSON), the caller must produce the
notJSON error response itself — crate::error_invocation and
crate::request_error with JmapError::not_json() handle that case.
parse_request only validates the JMAP structure of an already-parsed value.
§Caller responsibility: resource limits
Because this function works on an already-parsed serde_json::Value, it
cannot enforce the byte-size or JSON-nesting-depth limits that determine
whether the input is safe to walk on a worker thread. Those limits MUST
be applied by the HTTP integration before parse_request is called:
- Body size cap. Apply a maximum request-body size before reading the
body into memory. RFC 8620 §3 defines
maxSizeRequestas a session capability the server advertises; the byte cap MUST be<=that value. A sensible default is 10 MiB. Inaxum, wrap your router withtower_http::limit::RequestBodyLimitLayer; inhyper, usehttp_body_util::Limited; inwarp, pairwarp::body::content_length_limitwithwarp::body::bytes. - JSON nesting depth cap. Use
serde_json::from_slice(which honoursserde_json’s recursion limit) rather than constructing aValueby hand.serde_json’s default 128-level recursion limit is intentionally loose; deployments that face untrusted clients should consider rejecting request bodies that exceed ~32 levels of JSON nesting before passing them here. 32 levels is well above any legitimate JMAP request shape. - Per-pointer recursion. ResultReference paths are walked by an internal helper that carries its own depth cap, so integrators do not need additional guards on the path string itself once the body-size and JSON-depth limits are in place.
Failing to enforce these limits exposes the dispatcher to memory and stack-exhaustion DoS on adversarial input. The library cannot apply them itself because they belong to the HTTP layer, not the JMAP layer.
§Errors
Returns JmapError::not_request() if the value does not match the
JmapRequest schema. Returns
JmapError::limit("maxCallsInRequest") if the method
call count exceeds max_calls.