Skip to content

fix(deps): update dependency org.mock-server:mockserver-client-java to v7.3.0#1161

Merged
SylvainJuge merged 1 commit into
mainfrom
renovate/org.mock-server-mockserver-client-java-7.x
Jul 1, 2026
Merged

fix(deps): update dependency org.mock-server:mockserver-client-java to v7.3.0#1161
SylvainJuge merged 1 commit into
mainfrom
renovate/org.mock-server-mockserver-client-java-7.x

Conversation

@elastic-renovate-prod

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
org.mock-server:mockserver-client-java (source) 7.2.0 -> 7.3.0 age confidence

Warning

Some dependencies could not be looked up. Check the Dependency Dashboard for more information.


Release Notes

mock-server/mockserver-monorepo (org.mock-server:mockserver-client-java)

v7.3.0

Added
  • Typed client methods for control-plane operations that previously needed a hand-written REST call. The
    client libraries gain first-class methods for clock control (freeze / advance / reset / status), metrics
    (the JSON counter snapshot and the Prometheus scrape), configuration read/update, Pact import / export / verify,
    the file store (store / retrieve / list / delete), HAR and Postman import, the high-level operating mode
    (SIMULATE / SPY / CAPTURE), and generating expectations from a WSDL — so these no longer require a manual
    PUT /mockserver/… request. Rolling out across the Java, Node, Python, Ruby, Go, .NET, Rust and PHP clients.
Security
  • Fixture redaction now also masks credentials in query strings and streamed bodies, and fails closed on
    unparseable secrets.
    When redacting recorded traffic (HAR/Postman imports, the LLM optimisation report, the
    MCP capture tools) the redactor previously only masked sensitive headers and named JSON body fields. It now also
    (a) masks the values of credential-bearing query parameters by default (such as key, api_key, apikey,
    access_token, token, signature, sig, and the AWS SigV4 X-Amz-Signature/X-Amz-Security-Token) —
    e.g. Gemini's ?key= API key; (b) redacts configured fields inside each Server-Sent-Events data: payload of
    a streamed body, leaving non-JSON markers such as [DONE] intact (and failing closed on a data: payload it
    cannot parse that still mentions a configured field); and (c) when a body is configured for field redaction but
    cannot be parsed yet still mentions a configured field name, replaces the whole body rather than risk leaking it.
    Ordinary unstructured bodies (plain text, HTML, decoded binary) that mention no configured field are left
    unchanged.
  • A2A client builders: the custom-handler regex messagePattern is now escaped completely. Every client
    library (Java, Node, Python, Ruby, Go, Rust, PHP, .NET) inlines messagePattern into a JSONPath =~ /…/ regex
    literal but previously escaped only the / delimiter, so a pattern ending in a lone backslash (or containing
    \/) could escape the closing delimiter and break out of the regex literal into the surrounding JSONPath/JSON
    (CodeQL rb/incomplete-sanitization). The escaping now preserves valid regex escape sequences (e.g. \d) while
    neutralising the delimiter-breakout; normal patterns are unaffected.
  • Dashboard load-scenario report download now validates the URL scheme. The "download report" action passed a
    URL assembled from the user-configured connection to window.open without checking its scheme; it now opens the
    report only when the URL resolves to http/https, ruling out javascript:/data: redirection (CodeQL
    js/client-side-unvalidated-url-redirection).
  • /bind and /stop now honour control-plane authentication/authorization. These mutating lifecycle
    endpoints were serviced before the auth gate; they now require the same control-plane auth as
    /mockserver/configuration. Default deployments with no control-plane auth configured are unaffected, and
    /status / /ready remain open for health probes. Closes the lifecycle-endpoint gap noted in 7.2.0.
  • MCP tool calls now honour control-plane authorization. With controlPlaneAuthorizationEnabled, each MCP
    tool is classified read vs mutate (fail-closed) and checked against the same role model as the HTTP control
    plane, so a read-only principal can no longer invoke mutating MCP tools (create/clear/reset/…). Default
    (authorization disabled) behaviour is unchanged; enforced across HTTP and HTTP/3, single and batch. Closes
    the per-tool MCP gap noted in 7.2.0.
  • Control-plane JWT validation cross-request race fixed. A single shared JWTValidator reconfigured the
    Nimbus processor (key selector + claims verifier) on every call, so concurrent control-plane requests could be
    verified against another request's policy. The processor is now configured once and validate() is stateless.
  • Remote JWKS / OIDC discovery fetches are now bounded. JWKS-key-set and OIDC discovery-document fetches on
    the authentication path used the JOSE library defaults (infinite connect/read timeout, no size limit); they now
    use finite timeouts and a size cap, so a slow or hostile identity-provider endpoint can no longer hang the auth
    path or be used as an amplification vector.
  • Velocity templates can no longer fetch arbitrary URLs or read local files. The Apache Velocity
    ImportTool (which exposes $import.read(url|file)) was registered in the template toolbox; it has been
    removed, closing an SSRF / local-file-disclosure vector in response templates.
  • mTLS control-plane authentication rejects expired client certificates. Client-certificate authentication
    validated only that the certificate chained to the configured CA; it now also enforces the certificate
    validity window, so an expired or not-yet-valid (but correctly signed) client certificate is rejected.
  • Mock OIDC client-secret comparison is now constant-time.
Added
Load injection, chaos & SRE
  • Chaos experiments can assert an SLO and emit a verdict. A chaos experiment may now carry an optional
    sloCriteria; on termination MockServer attaches a terminal experimentVerdict (PASS / FAIL /
    INCONCLUSIVE) evaluated strictly over the experiment's window — PASS only if every objective held
    throughout, FAIL on any breach or auto-halt, INCONCLUSIVE below the minimum sample count. Turns
    "inject faults" into "verify resilience held."
  • SLO-breach auto-halt for chaos experiments. An experiment carrying sloCriteria is halted immediately
    (status halted_by_slo_breach, verdict FAIL) when an SLO objective is breached mid-run. No behaviour
    change when sloCriteria is absent. The dashboard's chaos panel now shows the terminal experimentVerdict
    (PASS / FAIL / INCONCLUSIVE) with per-objective observed-vs-threshold detail.
Request matching & response generation
  • JavaScript response templates now have a configurable execution timeout. A runaway or malicious
    JavaScript template (for example one containing an infinite loop) could previously pin the data-plane
    worker thread handling that request indefinitely. A new javascriptTemplateExecutionTimeout property
    (milliseconds) caps how long a template may run; on expiry a watchdog cancels the evaluation and the
    request fails fast with a clear, logged timeout error. The default is 5000 (5 seconds), far longer
    than any legitimate template needs. Set it to 0 (or a negative value) to disable the timeout and
    restore the previous unbounded behaviour. NOTE: this introduces a bounded behaviour change — templates
    that genuinely run longer than 5 seconds (previously allowed) will now be cancelled unless the timeout
    is raised or disabled.
  • Mustache response templates can now read scenario state by name. Velocity
    ($scenario.get('orderId')) and JavaScript (scenario.get('orderId')) could already read
    scenario/captured state in a response template; the Mustache engine now exposes the same through a
    section lambda — {{#scenario.get}}orderId{{/scenario.get}}, where the state name is the section
    body (jmustache cannot pass a method argument inline the way Velocity and JavaScript can). This
    completes capture → template value reuse across all three template engines, so an id captured
    from one request can be returned in the response body of a later request regardless of template
    engine. Documented on the Stateful Scenarios page with a per-engine example.
  • Closest-match hint on unmatched requests (closestMatchHintEnabled, default on). When a request
    matches no expectation, the 404 response now carries a compact, length-bounded
    x-mockserver-closest-match-hint header naming the closest expectation and the first field that differed —
    answering "why didn't my mock match?" without enabling verbose diagnostics. Set closestMatchHintEnabled=false
    to suppress. (The opt-in attachMismatchDiagnosticToResponse, which adds a full JSON diagnostic body, is
    unchanged and still off by default.)
OpenAPI & contract testing
  • Validate recorded traffic against an OpenAPI spec (PUT /mockserver/trafficValidate). A new
    control-plane endpoint validates the request/response traffic MockServer has already recorded against a
    provided OpenAPI spec (URL, file path, or inline), returning a structured pass/fail report
    (totalRequests / passed / failed / allPassed plus per-request matchedOperation, requestErrors,
    and responseErrors) — mirroring the /contractTest report. The endpoint is gated by the same
    control-plane authentication as its siblings, and a spec URL is fetched only after passing the same SSRF
    policy enforced on proxy/forward paths.
  • Java client helpers for contract testing & Pact. The Java MockServerClient now exposes fluent, typed
    methods for the contract-testing endpoints: contractTest(spec, baseUrl[, operationId]),
    trafficValidate(spec), pactImport(json), pactExport(consumer, provider), and pactVerify(json). The
    contract-test and traffic-validation reports parse into typed ContractReport / ContractResult objects so
    callers no longer hand-roll raw HTTP.
  • Per-import realistic example generation. OpenAPI imports can now request realistic (Datafaker) example
    values for a single import via a "realisticValues": true entry in the reserved __generationOptions__
    map (alongside the existing seed and fieldOverrides options), without changing the global
    generateRealisticExampleValues configuration. When the entry is absent, behaviour is unchanged and the
    global default still applies.
Dashboard UI
  • New "MCP Health" dashboard panel. When a coding-assistant CLI is proxied through MockServer, its MCP
    servers (e.g. chrome-devtools, devbot) are frequently the real latency bottleneck. The panel aggregates
    captured MCP (JSON-RPC) traffic per server and shows, worst-first, each server's call count, error count and
    rate (JSON-RPC errors or non-2xx responses), median / p95 / max latency, and its slowest method — with slow
    (≥5s) and erroring servers flagged — so it is obvious which MCP server is stalling, rather than guessing.
  • Anonymous, cookieless dashboard usage analytics (PostHog Cloud EU). The dashboard reports coarse, enumerated usage events (app_open, view_change, feature_used, error_shown) to a cookieless, EU-hosted PostHog project to help improve the UI. No request URLs, hostnames, headers, bodies, or expectation data are ever sent, and no tracking cookie is set. The official Docker images ship with this enabled; it is inactive in any build without dashboardAnalyticsEndpoint + dashboardAnalyticsKey (so plain JARs/WARs and source/fork builds send nothing). Disable globally with dashboardAnalyticsEnabled=false (or MOCKSERVER_DASHBOARD_ANALYTICS_ENABLED=false); respects Do Not Track, Global Privacy Control, and a per-browser opt-out banner. See dashboard privacy.
  • Official binary launcher bundles now also report anonymous cookieless dashboard usage analytics, joining the Docker images and Helm deployments. The plain downloadable JAR and any embedded/library/dependency use remain inert (no endpoint or key configured). Analytics events from all official artefacts now include a distribution label (from the new dashboardAnalyticsDistribution config property) identifying which artefact produced the event (docker-standard, docker-graaljs, docker-clustered, helm, or binary); values outside the closed allow-list are normalised to unknown — free text is never forwarded.
  • SLO verification dashboard panel. A new dashboard view authors service-level objectives (latency
    p50/p95/p99, error-rate) and runs them against the existing /mockserver/verifySLO endpoint, showing
    observed-vs-threshold per objective and an overall PASS / FAIL / INCONCLUSIVE verdict.
  • Dashboard remembers where you were. The active view and per-panel search/filter terms persist across
    reloads, and the view is reflected in the URL hash (e.g. #/contract) so views are linkable. A first visit
    still opens Get Started.
  • Dashboard search-operator hints. The search box now advertises its operators (status:>=400,
    method:POST, path:/api/*, /regex/) via the placeholder and an accessible help tooltip.
Client libraries
  • All client libraries now expose the full load-scenario surface. The Java, Node, Python, Ruby, Go,
    .NET, PHP, and Rust clients gained the new scenario fields (thresholds, abortOnFail, abortGraceMillis,
    pacing, feeder, stepSelection, per-step captures/weight, profile shape), the new run-status
    fields (p999Millis, droppedIterations, verdict, abortedByThreshold, thresholdResults), and three
    new methods — getLoadScenarioReport (with optional junit format), generateLoadScenarioFromOpenAPI,
    and generateLoadScenarioFromRecording.
  • Fluent when().respond() DSL in the Node client. The Node client now offers a chainable
    when(request).respond(response) — plus .forward(), .error(), .callback(), and
    .withTimes() / .withTimeToLive() / .withPriority() builders — mirroring the Java client, alongside the
    existing procedural methods (which are unchanged).
  • Opt-in per-test reset for the JUnit 5 extension. @MockServerSettings(resetBeforeEach = true) resets the
    shared MockServer before each test (matching the JUnit 4 rule and Spring listener). Default off, so existing
    behaviour is unchanged.
Clustering & observability
  • New mock_server_forward_upstream_protocol metric. A Prometheus counter labeled by upstream_host and
    protocol records the protocol each forward/proxy connection actually negotiated to the upstream (http2 via
    ALPN, or http1_1), with a matching DEBUG log. This is the authoritative way to confirm whether
    forwardProxyHttp2Upgrade is taking effect — the recorded request only carries the inbound protocol, not the
    upstream-negotiated one, so a forward stuck on http1_1 to a backend that withholds its streaming SSE head
    over HTTP/1.1 (a cause of high forward time-to-first-byte) was previously invisible.
  • Standard OTLP endpoint fallback. When mockserver.otelEndpoint / MOCKSERVER_OTEL_ENDPOINT is unset,
    MockServer now falls back to the OpenTelemetry-standard OTEL_EXPORTER_OTLP_ENDPOINT environment variable.
Proxy & TLS setup
  • New forwardProxyHttp2Upgrade setting (default off). Forwards a secure request to the upstream over HTTP/2 even when the inbound client is HTTP/1.1 (ALPN-negotiated, automatic fallback to HTTP/1.1 if the upstream does not offer HTTP/2; TLS only). This fixes a header-timeout some streaming upstreams exhibit, where the Server-Sent Events response head is sent immediately over HTTP/2 but withheld over HTTP/1.1.
  • Copy-paste proxy setup at startup. The new mockserver.proxySetupLogging property
    (env MOCKSERVER_PROXY_SETUP_LOGGING, default false; auto-enabled by the standalone JAR, Docker image,
    and mockserver CLI) writes the active CA certificate to mockserver-ca.pem in the dynamic-SSL directory
    at startup and prints a "Proxy Setup" block with ready-to-paste environment variable exports (HTTPS_PROXY,
    NODE_EXTRA_CA_CERTS, SSL_CERT_FILE, REQUESTS_CA_BUNDLE) for both Unix and Windows PowerShell. The
    block includes a security warning when the default public CA is in use. Embedded usage
    (new ClientAndServer(...)) stays silent by default to avoid polluting test output; when proxySetupLogging
    is off, the CA file is written on the first GET /mockserver/proxyConfiguration call instead. The endpoint
    itself is always available regardless of this setting.
  • GET /mockserver/proxyConfiguration endpoint. Returns the CA certificate path, CA PEM, proxy address,
    environment variable exports, and a flag indicating whether the default public CA is in use. Responds with
    JSON by default or a plain copy-paste text block when called with Accept: text/plain. Never exposes the
    private key.
  • --proxy-setup flag for a unique, secure CA. The new --proxy-setup CLI flag (property
    mockserver.proxySetup, env MOCKSERVER_PROXY_SETUP, default false) forces generation of a unique local
    CA on first startup, equivalent to dynamicallyCreateCertificateAuthorityCertificate=true. Recommended for
    any shared, persistent, or team-facing proxy deployment. Without it, MockServer uses the built-in default CA
    whose private key is published in the git repository (safe only for isolated local development).
  • Bounded-memory event log + disk capture for proxying LLM / large-body traffic without running out of
    memory.
    Proxying large request/response bodies (LLM tool schemas, growing conversation context, accumulated
    SSE) previously retained every exchange in full in the in-memory event log, which is bounded only by entry
    count (maxLogEntries), never by size — so a long capture session could exhaust the heap and crash the
    proxy. Three new opt-in properties address this: mockserver.maxEventLogSizeInBytes (env
    MOCKSERVER_MAX_EVENT_LOG_SIZE_IN_BYTES, default 0 = disabled) caps the retained body bytes and evicts the
    oldest entries from memory once exceeded; mockserver.persistRecordedRequestsToDisk (env
    MOCKSERVER_PERSIST_RECORDED_REQUESTS_TO_DISK, default false) with mockserver.persistedRecordedRequestsPath
    (default recordedRequests.ndjson) appends every proxied exchange — full request and response — as one compact
    JSON object per line (NDJSON) to disk as it completes, flushed per line, so the complete session survives even
    as the in-memory window evicts; and mockserver.maxLoggedBodyBytes (env MOCKSERVER_MAX_LOGGED_BODY_BYTES,
    default 0 = unlimited) truncates bodies kept in memory beyond a byte limit (marking the copy with an
    x-mockserver-body-truncated header) without affecting the disk archive. The NDJSON archive honours
    redactSecretsInLog, masking credentials on disk exactly as the dashboard does. The recommended pairing —
    byte budget plus disk capture — keeps memory bounded while disk holds everything; the
    mockserver-ui/scripts/launch-with-llm-capture.sh capture launcher now enables it by default (2 GB heap,
    256 MB byte budget, NDJSON disk capture).
Changed
  • TLS/decoder fault logs now name the SNI host. When a client's TLS handshake through the proxy fails
    (e.g. SSLHandshakeException: Received fatal alert: unknown_ca, meaning the client does not trust
    MockServer's CA), the WARN log now appends the SNI hostname the connection was for — e.g.
    … closing pipeline [id: 0x…] (SNI: chatgpt.com) — across the relay, SOCKS, port-unification, binary-proxy,
    MCP and dashboard/websocket handlers, so the failing target/client is identifiable instead of anonymous. The
    message is unchanged when no SNI was negotiated.
  • Dashboard UI titles are now consistently Title Case. Page/view headings, section headings, dialog
    titles, tab labels, navigation labels, and the tools/clear menu items now use Title Case throughout
    (e.g. "Server configuration" → "Server Configuration", "MCP server health" → "MCP Server Health"),
    so a menu item and the dialog it opens always match. Acronyms and brand names (MockServer, AsyncAPI,
    OpenAPI, gRPC, OIDC, SAML, SLO, CRUD, MCP, LLM, Pact) are preserved, and descriptive/help text, tooltips,
    and form labels are unchanged.
  • generateFromRecording in TEMPLATIZED mode now reproduces the recorded traffic mix. Each generated
    step's weight is set to the route's observed hit count and the scenario uses stepSelection: WEIGHTED,
    so replaying picks routes in proportion to how often they appeared in the recording (instead of plain
    ordered steps). VERBATIM mode is unchanged.
  • Docker images cap the JVM heap at 75% of the container memory limit (-XX:MaxRAMPercentage=75.0, in
    every published image that runs the server — standard, snapshot, root, root-snapshot, graaljs, local, and
    clustered), making memory use predictable and avoiding OOM-kills that looked
    like hangs. Always run with an explicit container memory limit. To set a fixed heap, pass an explicit -Xmx
    (a second MaxRAMPercentage via JAVA_TOOL_OPTIONS has no effect — it is applied before the image's flag).
    A build-time guard (.buildkite/scripts/steps/docker-validate-sync.sh) now fails the build if any
    server image's entrypoint is missing the cap, so it cannot drift back out of one variant.
    The Helm chart now ships commented resources and app.jvmOptions examples.
  • Generated TLS certificate validity extended to 10 years (was 365 days) for the dynamically generated CA,
    leaf/server, and HTTP/3 self-signed certificates, so pinned-CA test setups no longer expire after a year.
  • Dashboard navigation reorganised into grouped menus. The dashboard's views are now organised into six
    groups (Mock / Observe / Verify / Resilience / AI / Inspect) with submenus, replacing the flat overflow tab
    bar, so features are easier to discover.
  • The Trace view is now reachable from the AI menu as well as Observe. Trace groups related requests —
    including LLM agent runs — so it is now listed under AI alongside LLM Optimise, while remaining under Observe,
    making it easier to find when debugging multi-step AI flows.
  • The Trace view collapses a multi-turn LLM conversation into one growing thread. A stateless coding-assistant
    CLI (e.g. the OpenAI Codex backend used by opencode) resends its entire growing conversation/reasoning context
    on every turn, so consecutive recorded requests each "contained everything so far" and the view read as endless
    duplicates. Consecutive requests whose message history is a growing prefix of the next (same provider and host)
    now render as a single conversation showing each turn's new content, instead of N full-history blobs. Grouping
    is conservative (edited history, a different provider, or a different host never merge) and non-destructive — the
    raw per-request data is still reachable.
  • Expectation matching scales to large expectation sets. A candidate index buckets literal
    (method, exact-path) expectations so a request evaluates only plausible candidates instead of scanning
    every expectation; non-literal matchers (regex/notted/optional/schema/path-param) are always checked, so
    matching is byte-for-byte unchanged. The index engages automatically only above a size threshold (default
    64, overridable via -Dmockserver.candidateIndexThreshold); small expectation sets run the unchanged
    linear scan, so there is no regression at small scale and a large speed-up at thousands of expectations.
Fixed
Correctness & reliability
  • HTTP/2 clients through the forward/CONNECT proxy no longer hang when the upstream is also HTTP/2. When a client
    connected to MockServer's HTTPS forward proxy over HTTP/2 and MockServer forwarded to an upstream that also served
    HTTP/2, Netty's inbound HTTP/2→HTTP adapter tagged the decoded upstream response with a synthetic
    x-http2-stream-id header carrying the upstream stream id. That internal header leaked through the response
    mappers and was re-emitted to the client, so the response was written on the wrong (upstream) stream id — the
    client's HTTP/2 codec rejected it with a PROTOCOL_ERROR/GO_AWAY and the request hung until timeout. The
    response mappers now strip the Netty x-http2-* extension-header family so the outbound stream id is governed
    solely by the inbound request's stream id. HTTP/1.1 clients and directly-mocked HTTP/2 responses were never
    affected; captured/recorded responses also no longer carry the internal x-http2-stream-id header.
  • Millisecond timeouts are now settable under their unit-bearing …InMillis names, fixing silently-ignored overrides.
    The Java API (e.g. Configuration.maxSocketTimeoutInMillis()) and the /mockserver/configuration JSON expose these
    settings under …InMillis names, but the system property / environment variable were only read under the unit-less
    mockserver.maxSocketTimeout / MOCKSERVER_MAX_SOCKET_TIMEOUT form. Setting the natural
    -Dmockserver.maxSocketTimeoutInMillis=… (the name shown everywhere else) was therefore silently dropped and the
    20s default stood — long enough to 502 a healthy but slow first-byte response (e.g. a reasoning LLM backend that
    takes longer than 20s to emit its first token when proxied/forwarded). MockServer now also accepts the unit-bearing
    mockserver.maxSocketTimeoutInMillis, mockserver.socketConnectionTimeoutInMillis and
    mockserver.maxFutureTimeoutInMillis names (and their MOCKSERVER_*_IN_MILLIS environment-variable forms) as exact
    synonyms for the existing names — set whichever you prefer. The primary (unit-less) name is read first, so a value
    applied at runtime via the programmatic setter is never silently overridden by a launch-time alias.
  • Recorded streaming responses no longer pin the live streaming sink in memory. Each captured streaming
    (SSE) forward/proxy exchange stored a log entry whose response still referenced the live streaming body — its
    in-memory capture buffer, the upstream event loop, and the per-chunk callbacks — for the entry's whole lifetime
    in the log ring buffer, roughly doubling per-entry memory and pinning event-loop-adjacent objects. The retained
    log copy now holds only the fixed captured bytes and releases the live streaming reference.
  • forwardProxyHttp2Upgrade now applies to every forward route, fixing slow streaming captures. The
    HTTP/2-upgrade setting was honoured only by matched forward() expectations; it now also covers the
    transparent (unmatched) proxy path that most LLM/agent capture uses and the proxyPassMappings reverse-proxy
    route. Previously a coding-assistant CLI proxied over HTTP/1.1 was always forwarded upstream over HTTP/1.1, and
    some streaming backends (notably the OpenAI Codex SSE endpoint used by the opencode CLI) withhold the
    response head over HTTP/1.1 and only flush at completion, so time-to-first-byte collapsed to total time and
    surfaced as a client-side streaming timeout. With forwardProxyHttp2Upgrade enabled, a secure request on any
    forward route is now forwarded upstream over HTTP/2 via ALPN (falling back to HTTP/1.1 if the upstream
    declines), so the backend streams the head immediately. Off by default; only the opt-in flag with a secure
    (https) target triggers it.
  • Streamed responses with no Content-Type are no longer buffered, fixing a streaming header-timeout (notably
    for opencode).
    MockServer previously relayed a response incrementally only when the upstream advertised
    Content-Type: text/event-stream; a backend that streams Server-Sent Events with no content-type at all —
    notably the OpenAI Codex endpoint used by opencode — was buffered to completion before any headers were sent,
    so the client failed with "Provider response headers timed out after 10000ms". Streaming is now driven by the
    client's streaming intent (an Accept: text/event-stream header or a "stream": true request body),
    propagated per request to both the forward path and the transparent (CONNECT) loopback relay, so the response
    head reaches the client immediately regardless of the upstream's content-type. Ordinary buffered responses
    (including chunked-without-Content-Length servlet responses) and FORWARD_REPLACE overrides are unaffected.
  • A stalled upstream on a reused pooled keep-alive connection now times out instead of hanging. With the
    opt-in forward connection pool (forwardConnectionPoolKeepAlive) enabled, a pooled keep-alive connection
    carries no read timeout while it sits idle in the pool (a blanket one would fire during legitimate idle
    keep-alive). But a request dispatched on such a channel — a reused connection, or a fresh pooled channel's
    first request — was left with nothing to bound it, so an upstream that connected/kept-alive but then went
    silent hung the request until the far larger forward future timeout. An in-flight read timeout
    (maxSocketTimeout) is now armed when a request is dispatched on a pooled channel and removed again when the
    channel is returned to the pool, so a stalled reuse fails promptly. The default (pooling off) path is
    unchanged.
  • A streamed response is bounded by the streaming idle timeout, not the 20s socket read timeout. When a
    response switches to streaming, the per-request socket read timeout (maxSocketTimeout, default 20s) is now
    always replaced by the stream-appropriate idle bound (streamIdleTimeoutSeconds, default 60s), so a streaming
    LLM response that pauses longer than 20s between chunks (model reasoning) is not cut off mid-stream. Setting
    streamIdleTimeoutSeconds=0 now genuinely runs the stream unbounded as documented (previously the 20s socket
    timeout was left armed, truncating long inter-chunk gaps). The default (60s) is unchanged.
  • Large PUT /mockserver/retrieve and the LLM optimisation report no longer stall logging or time out.
    Retrieving logs, requests, recorded expectations, or request-responses serialized the (potentially large, e.g.
    captured streaming bodies) result inside the single log-consumer thread's callback, which could exceed the
    retrieve future timeout and — worse — block all further logging (filling the ring buffer and dropping events)
    while it ran. Every retrieve branch — LOGS, REQUESTS, RECORDED_EXPECTATIONS, and REQUEST_RESPONSES in
    all its formats (JSON, log entries, HAR, OpenAPI, Postman, Bruno, cURL) — now materializes the (cheap, redacted)
    result on the consumer thread and runs the expensive serialization on the caller thread; the LLM
    optimisation-report endpoint likewise builds its report off the Netty event loop. Output is byte-for-byte
    identical; only the thread doing the work changed.
  • Load-scenario status no longer reports a transient null while a run is completing. The orchestrator
    removed a finishing run from its active map before publishing the run's terminal status, so a status poll
    landing in that brief window saw neither and returned null. The terminal status is now published before the
    run is de-registered, so statusFor/getStatus always observe either the live or the completed status.
  • SSL/decoder faults in the proxy/relay handlers are now logged at WARN instead of being silently dropped,
    so genuine TLS/decoder problems are visible without the noise of benign connection closes.
  • LLM streaming pacing above 1000 tokens/sec is preserved. Sub-millisecond per-token delays were
    integer-truncated to 0 ms (flattening fast streams); pacing now accumulates with fractional carry so
    cumulative timing stays accurate.
  • Coding-assistant LLM traffic is recognised resiliently, including opencode's OpenAI Codex backend. The
    opencode CLI calls the OpenAI Responses API through its Codex backend at
    chatgpt.com/backend-api/codex/responses, a non-standard path the detectors did not match — so its calls were
    recorded under the generic Traffic view but never appeared in the LLM Traces or LLM Optimise views. Responses-API
    detection (LlmProviderSniffer, ProviderDetector, and the dashboard's llmTraffic.ts) now matches the Codex
    path alongside the hosted /v1/responses, and the chatgpt.com host on it. Detection also gains a host/path-
    independent body-shape fallback (read-only analysis only — Traffic, LLM Traces, LLM Optimise; never the live
    forward/cost path): LLM traffic is recognised from its wire format, so a coding assistant that moves to a new
    endpoint or a private gateway, or a new tool, stays classified without a code change. Claude Code (/v1/messages)
    and Tabnine CLI (…/chat/completions) were already recognised.
  • A streamed proxy response with no Content-Type is logged as readable text, not empty binary. The captured
    body of a streamed forward response with no content-type (opencode's OpenAI Codex SSE backend) was stored as a
    BINARY body, so it appeared empty in the dashboard's LLM Traces / Optimise text views. The captured bytes are
    now sniffed when no content-type is present — UTF-8 text (SSE/JSON) is stored as a readable STRING, while
    genuinely binary streams stay BINARY. Content-typed responses are unchanged.
  • HTTP/2 forwarded responses now stream incrementally instead of being buffered. The HTTP/2 forward client was
    rebuilt on the same multiplex stack the server uses (Http2FrameCodec + Http2MultiplexHandler), reusing the
    existing HTTP/1.1 streaming relay per stream — a streamed upstream response (SSE) now has its head relayed to the
    client as soon as it arrives rather than after the whole body. Non-streaming HTTP/2 responses are still aggregated.
  • More consistent LLM provider detection across the proxy, traces and optimise views. Embeddings/moderations
    requests are no longer mis-classified as the OpenAI Responses API; the MCP provider=AUTO analysis now uses the
    same host + body-shape detection as the dashboard and optimisation report; and Cohere, Voyage, Vertex AI Gemini,
    and the AWS Bedrock Converse API are now recognised.
  • The LLM optimisation report classifies and prices calls more honestly. It now uses the response body when
    detecting the provider (a header-less Anthropic call is no longer mis-labelled OpenAI), and a call whose model
    has no known price — or only a placeholder rate — is flagged as unpriced/approximate instead of being shown as a
    confident $0.00. The copy-paste optimisation brief also masks obvious credential shapes in prompt text.
  • The dashboard renders more LLM responses correctly. Streamed OpenAI Chat Completions and Gemini responses
    that carry no Content-Type header now reassemble and display instead of showing empty; Anthropic prompt-cache
    tokens are surfaced; a hostile/malformed Server-Sent Events index can no longer exhaust browser memory; and a
    truncated or unparseable response body now shows a clear notice rather than a silent blank.
  • Captured credentials are masked in the dashboard. API keys and bearer tokens in Authorization, x-api-key,
    api-key, cookies and similar headers are masked in the Traffic raw/diff views (the original value is still used
    for replay), so a shared or screen-shared dashboard no longer exposes live credentials.
  • Forward DNS resolution moved off the calling thread. Forward actions hand the connect path an unresolved
    address so DNS runs on the Netty event loop; SSRF validation still resolves and rejects private/loopback
    targets first, and a missing SSRF guard was added to the forward-validate path.
  • Code-review hardening sweep — correctness, concurrency, resources and performance. A repo-wide review
    surfaced and fixed a set of latent defects:
    • Stale hashCode broke matching. KeyToMultiValue.replaceValues()/addNottableValues() mutated the
      value list without refreshing the cached hashCode (unlike addValue()), so a header/parameter object
      reused on the matching hot path (e.g. via ExpandedParameterDecoder) could violate the equals/hashCode
      contract. The cache is now refreshed on every mutation, and the 0-sentinel hashCode caches on
      HttpRequest/HttpResponse/Action/Not no longer defeat themselves when a hash legitimately computes to 0.
    • NullPointerException serialising a chunked response with no body — the chunked body encoder now guards a
      null body.
    • WebSocket object-callback disconnect bug. When a callback client disconnected mid-exchange the
      forward-object-callback handler wrote the HTTP response twice and left a CompletableFuture that never
      completed (pinning a scheduler thread until the future timeout); the disconnect path now writes once,
      unregisters the callback, and returns. Response/forward callback registry entries are also unregistered on
      every disconnect branch.
    • JavaScript response templates were fully serialised through an engine-wide lock even though each call
      already builds its own GraalVM context; the lock was removed so concurrent JS templates run in parallel.
    • Numerous unsynchronised lazy-init / check-then-act races hardened (template-engine and body-deserializer
      ObjectMappers, the OpenAPI parse cache via computeIfAbsent, JsonStringMatcher, the Java client's Netty
      client and event bus, action-handler template engines, LogEntry override cache, scheduler thread numbering).
    • Configuration round-trip gaps. controlPlaneScopeMapping, the proxy-pass mappings, and
      proxyRemoteHost/proxyRemotePort now round-trip through PUT /mockserver/config; an unrecognised
      logLevel now fails fast with a clear message instead of an NPE during start-up; the conventional
      mockserver.perExpectationMetricsEnabled property key is accepted (the legacy key still works).
    • Event loop no longer blocked. Connection-delay sleeps and awaitUninterruptibly() calls were removed
      from the proxy/SOCKS/relay event-loop paths; the outbound HTTP client now applies a read timeout so a
      stalled upstream cannot pin a connection/future indefinitely; CONNECT-relay aggregators are bounded to the
      configured maximum body size instead of ~2 GB.
    • Resource & memory leaks fixed. MemoryMonitoring now unregisters its log/expectation listeners on stop
      (and writes its CSV via try-with-resources); the LLM completion cache and quota registry are now bounded;
      gRPC gzip frames are capped on decompressed size (decompression-bomb guard).
    • Async broker mocking publish/subscribe lifecycle is synchronised, Kafka send failures are logged, and
      subscribers expose a health flag after a broker disconnect.
    • Clustered in-memory CAS no longer loses a concurrent write when an entry is swapped under the same key
      (identity-conditional remove/replace).
    • Hot-path allocations removed (case-insensitive header/parameter lookups, matcher-listener notification,
      load-metric label arrays), and generated TLS certificates are now anchored to issuance time rather than the
      JVM start time.
    • Control-plane endpoints can no longer be hijacked by an early (respondBeforeBody) expectation. A
      catch-all respondBeforeBody expectation (for example one seeded from an initialization file) was matched
      before the control-plane dispatch, so it could answer the server's own management requests (e.g.
      PUT /mockserver/reset). Early header matching now excludes the reserved /mockserver control-plane path
      prefix, so management endpoints always reach the control plane.
Dashboard UI
  • Dashboard LLM pricing corrected. The dashboard cost estimates were ~1 year stale and up to ~3× too high
    (e.g. Opus 4.8 shown at 15/75 instead of 5/25); the table is now synced to the server's pricing and guarded
    by a drift test.
IDE extensions (VS Code & JetBrains)
  • JetBrains plugin no longer uses internal/deprecated IntelliJ Platform APIs. A blocking IntelliJ Plugin
    Verifier gate now runs in CI against the full recommended IDE set (IntelliJ IDEA 2024.3 through the 2026.2 EAP)
    and rejects internal, deprecated, and scheduled-for-removal API usages — the same classes the Marketplace
    flags. The plugin's self-version lookup is resolved from its own plugin class loader
    (PluginAwareClassLoader.pluginDescriptor.version), because the id-based PluginManager.getPluginByClass(...) /
    PluginManagerCore.getPlugin(PluginId) lookups are both marked internal on newer platforms; the tool-window
    buttons fire their actions via the stable AnActionEvent.createEvent(...) + update/actionPerformed
    primitives instead of the deprecated ActionUtil.invokeAction(...); and the deprecated JBCefBrowser(...)
    constructors use the JBCefBrowser.createBuilder()...build() API. No behaviour change; keeps the plugin
    installable on current and future IDE builds.
OpenAPI & contract testing
  • OpenAPI format: date/date-time examples render as ISO strings again (#​2370).
    An inline example: '2021-01-30' on a type: string, format: date property was serialised in generated
    responses as epoch-millis (1611964800000) instead of the ISO string, because swagger-parser deserialises
    the example into a java.util.Date that the explicit-example path handed straight to Jackson. Date/date-time
    examples are now normalised back to their schema string form before serialisation (regression since 6.0.0).
Client libraries & integrations
  • Spring @MockServerTest works with JUnit 5 @Nested classes again (#​2371).
    Injecting the MockServerClient declared on an outer test class into a @Nested inner test instance threw
    IllegalArgumentException because the field was set on the inner instance rather than the enclosing instance
    that declares it. Injection now resolves the correct enclosing instance via the synthetic outer reference
    (regression since 6.0.0).
Build & dependencies
  • mockserver-core no longer triggers dependency-convergence errors in downstream builds
    (#​1970). Projects that depend on
    mockserver-core and run maven-enforcer's dependencyConvergence rule saw conflicts for guava, jsr305,
    rhino, libphonenumber, snakeyaml, commons-, slf4j-api, jackson- and jakarta.xml.bind-api, because those
    versions are pinned in MockServer's parent dependencyManagement (which is not transitive) while
    swagger-parser, json-patch, velocity and protobuf-java-util dragged in older transitive copies. The stale
    transitive edges are now pruned with <exclusion>s (the resolved classpath is unchanged — the pinned/newer
    versions already won nearest-wins), and jackson-dataformat-yaml and jsr305 are declared directly so a
    single version of each reaches consumers. (The mockserver-client-java half of this was fixed in 7.1.0.)

Configuration

📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Renovate Bot.

@elastic-renovate-prod elastic-renovate-prod Bot requested a review from a team as a code owner July 1, 2026 08:34
@elastic-renovate-prod elastic-renovate-prod Bot added changelog:skip dependencies Pull requests that update a dependency file labels Jul 1, 2026
@SylvainJuge SylvainJuge enabled auto-merge (squash) July 1, 2026 13:42
@SylvainJuge SylvainJuge merged commit 36a3419 into main Jul 1, 2026
25 checks passed
@SylvainJuge SylvainJuge deleted the renovate/org.mock-server-mockserver-client-java-7.x branch July 1, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-java changelog:skip dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant