Skip to content

fix(go,csharp,python,ruby,php,rust): strip query params from WireMock urlPathTemplate#16693

Open
dvdaruri-art wants to merge 2 commits into
mainfrom
devin/1782331347-fix-query-params-wiremock
Open

fix(go,csharp,python,ruby,php,rust): strip query params from WireMock urlPathTemplate#16693
dvdaruri-art wants to merge 2 commits into
mainfrom
devin/1782331347-fix-query-params-wiremock

Conversation

@dvdaruri-art

@dvdaruri-art dvdaruri-art commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes WireMock wire test generation for endpoints whose OpenAPI paths contain embedded query strings (e.g. Stainless overload pattern ?stainless_overload=methodName). WireMock's urlPathTemplate only matches the path portion — query params placed there cause stubs to never match.

Changes Made

packages/commons/mock-utils/src/index.ts

  • When an endpoint path contains ?, split it: path goes to urlPathTemplate, query params go to a new queryParameters matcher block
  • Added metadata.fullPathTemplate field to preserve the original full path (including query string) for disambiguation when looking up stubs
  • Helper methods: splitPathAndQuery(), parseQueryParams()

All 6 generator WireTestGenerators

Applied identical fix pattern across Go v2, C#, Python v2, Ruby v2, PHP, Rust:

// getWireMockConfigContent(): use fullPathTemplate for map key
const pathForKey = mapping.metadata.fullPathTemplate ?? mapping.request.urlPathTemplate;

// buildBasePath(): use full path for lookup, strip query for actual URL
const mappingKey = wiremockMappingKey({ method, requestUrlPathTemplate: fullPath });
let basePath = fullPath;
const queryIndex = basePath.indexOf("?");
if (queryIndex !== -1) basePath = basePath.substring(0, queryIndex);
  • generators/go-v2/sdk/src/wire-tests/WireTestGenerator.ts
  • generators/csharp/sdk/src/test-generation/mock-server/MockEndpointGenerator.ts
  • generators/python-v2/sdk/src/wire-tests/WireTestGenerator.ts
  • generators/ruby-v2/sdk/src/wire-tests/WireTestGenerator.ts
  • generators/php/sdk/src/wire-tests/WireTestGenerator.ts
  • generators/rust/sdk/src/wire-tests/WireTestGenerator.ts

Changelog entries added

  • generators/go/sdk/changes/unreleased/fix-wiremock-query-params.yml
  • generators/csharp/sdk/changes/unreleased/fix-wiremock-query-params.yml
  • generators/python/sdk/changes/unreleased/fix-wiremock-query-params.yml
  • generators/ruby-v2/sdk/changes/unreleased/fix-wiremock-query-params.yml
  • generators/php/sdk/changes/unreleased/fix-wiremock-query-params.yml
  • generators/rust/sdk/changes/unreleased/fix-wiremock-query-params.yml

Testing

  • All 6 generators compile successfully (pnpm turbo run compile)
  • Seed tests pass for Go and C# fixtures
  • CI verification pending

Link to Devin session: https://app.devin.ai/sessions/95554c85c0ec46eba848a62db064632f
Requested by: @dvdaruri-art


Open in Devin Review

…add as queryParameters matchers

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@dvdaruri-art dvdaruri-art requested a review from Swimburger as a code owner June 24, 2026 20:24
@dvdaruri-art dvdaruri-art self-assigned this Jun 24, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Open in Devin Review

Comment on lines +424 to +430
// Strip query string — query parameters embedded in the path (e.g. Stainless
// overload paths like "?stainless_overload=branchFrom") must be matched via
// the separate queryParameters field, not as part of urlPathTemplate.
const queryIndex = path.indexOf("?");
if (queryIndex !== -1) {
path = path.substring(0, queryIndex);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Shared buildUrlPathTemplate now strips query strings from urlPathTemplate, breaking key lookups in Python, Ruby, PHP, and Rust generators

The buildUrlPathTemplate method in mock-utils now strips query strings from the urlPathTemplate field of WireMockMapping. Only the Go v2 and C# generators were updated to use the new metadata.fullPathTemplate for disambiguation. The Python (generators/python-v2/sdk/src/wire-tests/WireTestGenerator.ts:769), Ruby (generators/ruby-v2/sdk/src/wire-tests/WireTestGenerator.ts:562), PHP (generators/php/sdk/src/wire-tests/WireTestGenerator.ts:431), and Rust (generators/rust/sdk/src/wire-tests/WireTestGenerator.ts:540) generators still key their wireMockConfigContent map by mapping.request.urlPathTemplate. When processing endpoints with embedded query strings (e.g., /path?stainless_overload=foo), the stored key is now "POST - /path" but their buildBasePath methods construct lookup keys with the query string intact ("POST - /path?stainless_overload=foo"), causing a mismatch. For Rust, this throws a fatal GeneratorError.internalError. For Ruby, it logs a warning and returns an unsubstituted path. For Python and PHP, the mapping lookup silently fails and path parameters are not substituted.

Affected consumer code patterns (all unchanged by this PR)

All four generators do:

// getWireMockConfigContent() - uses urlPathTemplate which now lacks query string
const key = this.wiremockMappingKey({ requestMethod: mapping.request.method, requestUrlPathTemplate: mapping.request.urlPathTemplate });

// buildBasePath() - uses raw endpoint.fullPath which still has query string
let basePath = endpoint.fullPath.head + parts;
const mappingKey = this.wiremockMappingKey({ requestMethod: endpoint.method, requestUrlPathTemplate: basePath });
Prompt for agents
The buildUrlPathTemplate method in mock-utils now strips query strings from urlPathTemplate, but only the Go v2 and C# generators were updated to handle this change. The Python v2, Ruby v2, PHP, and Rust generators still use mapping.request.urlPathTemplate as the key in getWireMockConfigContent() and construct lookup keys from endpoint.fullPath (which still includes query strings) in buildBasePath().

To fix this, each of the four affected generators needs two changes:
1. In getWireMockConfigContent(): Use mapping.metadata.fullPathTemplate ?? mapping.request.urlPathTemplate for the key (same as the Go v2 fix)
2. In buildBasePath(): Use the full path (including query string) for the mapping key lookup, then strip the query string from the actual base path used for URL construction

Affected files:
- generators/python-v2/sdk/src/wire-tests/WireTestGenerator.ts (getWireMockConfigContent at line 763, buildBasePath at line 779)
- generators/ruby-v2/sdk/src/wire-tests/WireTestGenerator.ts (getWireMockConfigContent at line 556, buildBasePath around line 390)
- generators/php/sdk/src/wire-tests/WireTestGenerator.ts (getWireMockConfigContent at line 427, buildBasePath at line 437)
- generators/rust/sdk/src/wire-tests/WireTestGenerator.ts (getWireMockConfigContent at line 534, buildBasePath at line 408)

See the Go v2 WireTestGenerator.ts lines 46-61 and 814-836 for the reference implementation of both fixes.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +816 to +828
let fullPath =
endpoint.fullPath.head +
endpoint.fullPath.parts.map((part) => `{${part.pathParameter}}${part.tail}`).join("");

if (!basePath.startsWith("/")) {
basePath = `/${basePath}`;
if (!fullPath.startsWith("/")) {
fullPath = `/${fullPath}`;
}

// Use the full path (with query string) for the mapping key lookup,
// since getWireMockConfigContent keys by fullPathTemplate when available.
const mappingKey = this.wiremockMappingKey({
requestMethod: endpoint.method,
requestUrlPathTemplate: basePath
requestUrlPathTemplate: fullPath

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 Fragment handling inconsistency between buildRawFullPath and Go v2 buildBasePath

The buildRawFullPath method in packages/commons/mock-utils/src/index.ts:446-449 strips URL fragments (e.g., #refresh) from paths, but the Go v2 buildBasePath at generators/go-v2/sdk/src/wire-tests/WireTestGenerator.ts:816-818 does NOT strip fragments when constructing the lookup key. For endpoints with fragments (like /oauth2/token#refresh), fullPathTemplate would be undefined (since buildRawFullPath produces the same as urlPathTemplate after fragment stripping), so the stored key would be "POST - /oauth2/token". But buildBasePath would produce "POST - /oauth2/token#refresh" as the lookup key. This is a pre-existing mismatch (it existed before this PR in the old code where fragments weren't stripped from the lookup key either), but it's worth noting that this PR doesn't fix it. If fragment-path endpoints exist in Go API specs, they'd still cause a fatal error at the throw GeneratorError.internalError on line 841.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

…mplate in additional generators

Apply the same fullPathTemplate fix to Python v2, Ruby v2, PHP, and Rust
generators. Uses mapping.metadata.fullPathTemplate (with fallback to
mapping.request.urlPathTemplate) as the key in getWireMockConfigContent(),
and strips query strings from basePath in buildBasePath() while preserving
the full path for mapping lookup.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration devin-ai-integration Bot changed the title fix(go,csharp): strip query params from WireMock urlPathTemplate fix(go,csharp,python,ruby,php,rust): strip query params from WireMock urlPathTemplate Jun 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

SDK Generation Benchmark Results

Comparing PR branch against median of 5 nightly run(s) on main (latest: 2026-06-24T05:18:39Z).

Full benchmark table (click to expand)
Generator Spec main (generator) main (E2E) PR (generator) Delta
csharp-sdk square 76s (n=5) 109s (n=5) 63s -13s (-17.1%)
go-sdk square 134s (n=5) 283s (n=5) 135s +1s (+0.7%)
php-sdk square 59s (n=5) 85s (n=5) 54s -5s (-8.5%)
python-sdk square 130s (n=5) 241s (n=5) 139s +9s (+6.9%)
ruby-sdk-v2 square 92s (n=5) 129s (n=5) 88s -4s (-4.3%)
rust-sdk square 183s (n=5) 174s (n=5) 173s -10s (-5.5%)

main (generator): generator-only time via --skip-scripts (includes Docker image build, container startup, IR parsing, and code generation — this is the same Docker-based flow customers use via fern generate). main (E2E): full customer-observable time including build/test scripts (nightly baseline, informational). Delta is computed against generator-only baseline.
⚠️ = generation exited with a non-zero exit code (timing may not reflect a successful run).
Baseline from nightly runs on main (latest: 2026-06-24T05:18:39Z). Trigger benchmark-baseline to refresh.
Last updated: 2026-06-24 21:03 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant