Skip to content

Commit 71832e2

Browse files
chore(deps): update dependency org.mock-server:mockserver-netty-no-dependencies to v7.3.0 (#2262)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [org.mock-server:mockserver-netty-no-dependencies](https://www.mock-server.com) ([source](https://redirect.github.com/mock-server/mockserver-monorepo)) | `7.2.0` → `7.3.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/org.mock-server:mockserver-netty-no-dependencies/7.3.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.mock-server:mockserver-netty-no-dependencies/7.2.0/7.3.0?slim=true) | --- ### Release Notes <details> <summary>mock-server/mockserver-monorepo (org.mock-server:mockserver-netty-no-dependencies)</summary> ### [`v7.3.0`](https://redirect.github.com/mock-server/mockserver-monorepo/blob/HEAD/changelog.md#730---2026-07-01) ##### 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](https://www.mock-server.com/mock_server/dashboard_privacy.html). - **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 `ObjectMapper`s, 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** ([#&#8203;2370](https://redirect.github.com/mock-server/mockserver-monorepo/issues/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** ([#&#8203;2371](https://redirect.github.com/mock-server/mockserver-monorepo/issues/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** ([#&#8203;1970](https://redirect.github.com/mock-server/mockserver-monorepo/issues/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.) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/prometheus/client_java). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNDIuMiIsInVwZGF0ZWRJblZlciI6IjQzLjI0Mi4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
1 parent b37723e commit 71832e2

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

  • prometheus-metrics-exporter-pushgateway

prometheus-metrics-exporter-pushgateway/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
<dependency>
3636
<groupId>org.mock-server</groupId>
3737
<artifactId>mockserver-netty-no-dependencies</artifactId>
38-
<version>7.2.0</version>
38+
<version>7.3.0</version>
3939
<scope>test</scope>
4040
</dependency>
4141
<dependency>

0 commit comments

Comments
 (0)