Skip to content

Make the mock server faithful to the backend: rate-limit headers + no_data 404s#9

Merged
MarketDataDev03 merged 1 commit into
mainfrom
improve_mock_server
Jun 1, 2026
Merged

Make the mock server faithful to the backend: rate-limit headers + no_data 404s#9
MarketDataDev03 merged 1 commit into
mainfrom
improve_mock_server

Conversation

@MarketDataDev03

Copy link
Copy Markdown
Collaborator

Make the mock server faithful to the backend: rate-limit headers + no_data 404s

Summary

Two divergences between examples/mock-server and the real backend (../api/)
were surfaced in review. Both are fixed here so consumer demos exercise the same
wire behavior a real consumer sees.

  1. Rate-limit headers were never emitted. The mock only set cf-ray and
    Content-Type, so client.getRateLimits() always returned null against it
    and the §10.3 exhausted-credits preflight path could not be exercised without
    hand-scripting all four headers on every step. The real backend attaches
    X-Api-Ratelimit-{Limit,Remaining,Reset,Consumed} to every response via
    update_user_quota (api/.../common/util/user_quotas_helper.py:162).

  2. Unknown routes returned the wrong envelope. The mock answered
    404 {"s":"error","errmsg":"..."}. The backend's custom_404
    (api/.../marketDataApi/views.py:50) returns 404 {"s":"no_data"}. This
    matters because the SDK parses {"s":"error"} into a thrown ParseError
    while {"s":"no_data"} is a successful empty response — so the mock made a
    no-data path look like a failure.

Changes

examples/mock-server/server.py

  • Add _default_ratelimit_headers() — emits all four x-api-ratelimit-*
    headers (all-or-nothing, matching RateLimitHeaders.parse), reset 24h out.
  • Inject them on the default response path and on scripted responses
    (via setdefault, so a step can override e.g. x-api-ratelimit-remaining: 0).
  • Unknown routes now return 404 {"s":"no_data"} (and inherit the rate-limit
    headers, just like the backend's custom_404).

examples/mock-server/README.md

  • Update the defaults table (404 → no_data) and document the rate-limit
    headers + how to script the exhausted-credits case.

Exhausted-credits scenario

The headers are scriptable, so driving the preflight is one step:

{"steps": [{"status": 200, "body": "{\"s\":\"ok\"}",
            "headers": {"x-api-ratelimit-remaining": "0",
                        "x-api-ratelimit-reset": "9999999999"}}]}

The step's remaining: 0 wins; the other three headers auto-fill.

Verification

Ran the server (uvicorn server:app) and hit it with curl:

  • GET /status/ (default) → 200 with all four x-api-ratelimit-* headers
    present → getRateLimits() now returns a real snapshot instead of null.
  • GET /v1/stocks/quotes/AAPL/ (unknown route) → 404 {"s":"no_data"} with
    rate-limit headers attached.
  • Script with x-api-ratelimit-remaining: 0 → step value wins, other three
    headers auto-fill.
  • python -m py_compile server.py → clean.

Regression check

  • Every {"s":"error"} body in examples/consumer-test/ is scripted explicitly
    via Step.of(...); none relied on the default 404 envelope, so the switch to
    no_data does not affect them.
  • ResponseFeaturesApp already scripted its own 404 {"s":"no_data"}, which is
    now consistent with the default.

Scope

Mock-server / examples only. No changes to the SDK's src/main or its JUnit
suite (the CapturingClient stub already covers these scenarios at the wire
level).

@codecov

codecov Bot commented May 29, 2026

Copy link
Copy Markdown

The author of this PR, MarketDataDev03, is not an activated member of this organization on Codecov.
Please activate this user on Codecov to display this PR comment.
Coverage data is still being uploaded to Codecov.io for purposes of overall coverage calculations.
Please don't hesitate to email us at support@codecov.io with any questions.

@MarketDataDev03 MarketDataDev03 merged commit ed36372 into main Jun 1, 2026
5 checks passed
@MarketDataDev03 MarketDataDev03 deleted the improve_mock_server branch June 1, 2026 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants