Skip to content

Client codegen: third-party API gaps (Boost-free TLS, proxy, decompress, Retry-After, 304, streaming, overall deadline) #189

Description

@cursor

Tracking issue for the ideal client-codegen / client-runtime setup needed by third-party HTTPS APIs.

Source: muchq/MoonBase#1390 (chess.com Smithy client). A third-party API exercises parts of the client runtime that first-party services never do. Ordered by what actually blocks or annoys that use case. Each item can graduate into its own issue when picked up.

Findings were read against master; worth re-confirming against consumer pins before implementing.

Motivation (in brief)

A generated smithy_cpp_client_library is Boost-free and depends only on @nlohmann_json + @zlib. The sole TLS-capable transport is //runtime:http_beast, which pulls ~53 Boost modules. api.chess.com is HTTPS, so a client-only binary currently pays that cost for TLS alone. Proxy support is also absent, which blocks smoke-testing generated clients from sandboxed / corporate-egress environments.

Feature requests

  • 1. A TLS transport that doesn't require Boost. (headline) SocketHttpClient is plaintext-only; BeastHttpClient is the sole TLS path. BoringSSL is already a direct dependency, so a TLS-capable socket transport on it (e.g. //runtime:http_tls) would add no new third-party dependency while keeping the two-library client footprint. A curl-backed transport is the other shape and would bring items 2 and 3 for free. With either in place, Create() could build an HTTPS transport from ClientConfig, and the "https endpoints need a TLS-capable transport" rejection stops being a foot-gun for external services.

  • 2. Proxy support (HTTP_PROXY / HTTPS_PROXY / NO_PROXY, CONNECT tunneling). Absent entirely today. Decides whether a generated client can run in sandboxed or corporate-egress environments. Worth pairing with a way to add a CA to the system roots instead of replacing them (tls.ca_pem currently replaces), since proxy environments need both.

  • 3. Response decompression. Gzip is request-side only (@requestCompression); nothing inspects Content-Encoding on a response. Nearly free: GzipDecompress already exists in //runtime:compression, which every generated client already depends on (@zlib already in the set). Pure plumbing plus an accept_encoding knob on ClientConfig.

  • 4. Honor Retry-After. RetryDelay is pure full-jitter exponential; a 429 with Retry-After: 30 is retried inside a window bounded by max_backoff (20 s default), ignoring the server. Parse both delta-seconds and HTTP-date forms and use as a floor, capped by policy.

  • 5. A first-class 304 / conditional-GET story. Smithy's @error is client or server only, so a 304 cannot be a modeled error; today it lands in GenericError with status == 304. For immutable archive APIs this is a large bandwidth win (If-Modified-Since → "unchanged, use your copy"). Ask: a typed way to express "not modified" in the outcome without pattern-matching a generic error.

  • 6. Streaming / sink-based response bodies. Responses are buffered whole then decoded, so peak memory is roughly two copies of a multi-MB body per in-flight request. A sink/callback API (or client-side @streaming blob output) would bound that.

  • 7. An overall deadline, not just a per-attempt one. request_timeout_ms is per attempt; SendWithRetries sleeps backoff between attempts, so with max_attempts = 3 the worst case is ~3× timeout plus backoff with no ceiling. Ask: overall_timeout_ms on ClientConfig, enforced across attempts.

Nice-to-haves (lower value): @httpLabel formatting hints (e.g. zero-padded integers — trivially caller-side today), and HTTP/2.

Related notes from the MoonBase write-up

  • Beast is already used for servers in that consumer; taking Beast for HTTPS now is fine, but these upstream requests should land so transport choice and model work can proceed independently.
  • Item 2 (proxy) cannot be worked around locally: without it, nobody can exercise a real HTTPS API from a sandbox regardless of which TLS transport is chosen.
  • System trust roots via set_default_verify_paths when tls.ca_pem is empty are good defaults; OCI images still need ca-certificates.

Filed from MoonBase#1390 so the upstream backlog captures the third-party client gaps before that work proceeds.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions