Repository navigation
Run Prism behind a proxy for array query params - #127
Merged
Merged
Conversation
The SDKs send array query params as `name[]=value`, but Prism looks them up under the exact name `name`. A required array param is therefore reported as missing and the generated contract test gets a 422, which fails archastro-js #85 on DELETE /api/v1/threads/{thread}/tags. The generated TypeScript and Python contract setup now starts Prism from a temporary spec copy with array query params optional. The published spec and the channel harness are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Replace the relaxed spec copy with a proxy, so Prism validates array query params against the unmodified spec. The SDKs send array query params as `name[]=value`, but Prism looks params up by their exact name. Relaxing required arrays in a spec copy got the requests through, but it stopped the contract tests from catching an SDK that drops a required array param, and Prism still never validated optional array params. Generated contract setup now runs `prism-proxy.mjs`. It starts Prism on a free port, listens on the test port once Prism answers, and rewrites `name[]=` to `name=` in the query before forwarding. TypeScript and Python emit the same script. The Python writer now uses `//` for the content-hash line of `.mjs` files. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
When a signal stopped Prism, the proxy exited with code 0, so setup errors read "exited with code 0". The proxy now exits with 128 plus the signal number, the usual shell convention: SIGKILL gives 137 and SIGTERM gives 143. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Review on ArchCode
Problem and intent
Generated SDK contract tests start a Prism mock from the OpenAPI spec and call it with the generated clients. The SDK runtimes send array query params as
name[]=value, which is what Platform expects. Prism looks query params up by their exact name, so it never seestags[]=xastags.This causes two problems:
DELETE /api/v1/threads/{thread}/tagsis the only one in the spec, and it fails 4 contract tests on archastro-js #85. That blocks the SDK release ArchDev web needs to drop an HTTP workaround for tag removal. The Python SDK would fail 8 tests on its next regeneration.group_by[]=bogus-valuegets a 200.Prism 5.14.2 and 5.16.0 behave the same, so upgrading doesn't help. Naming the param
tags[]in the spec gives a 422 for every form.The goal is contract tests that accept correctly encoded requests and still reject wrong ones, without changing the published contract.
What changed
Before: Prism listens on the test port and receives the SDK's
name[]=params under names it doesn't recognise.After: the generated setup runs
prism-proxy.mjs:name[]=toname=in the query string before forwarding. Paths, values, headers, bodies and status codes pass through unchanged.The TypeScript and Python setups emit the same script from
prism-proxy.ts. The Python writer now uses//for the content-hash line of.mjsfiles.This PR has two commits. The first relaxed required arrays in a copy of the spec, and the second replaces that with the proxy.
Unchanged:
Scope: generator contract-test emitters only, with no SDK runtime or API change.
Risk: low. This affects generated test setup only. The proxy adds a process to each contract run.
User impact: none directly. It unblocks the SDK release.
Testing
Each request below went through the proxy to Prism with the unmodified spec:
tags[]=xtags[]=x&tags[]=ytagstag[]=xgroup_by[]=bogus-valuetags=xCanonical end-to-end proof: no test in this repo runs real Prism. The proof is a manual run of each SDK's generated contract suite against real Prism, using a local build of this generator and the
0ce34f0spec.npm run test:contractinarchastro-jsis the JS run, andpytest tests/contractinarchastro-pythonis the Python one. Generated clients send real HTTP requests through the proxy, and the tests assert on Prism's responses.tags.removechanged to droptagsAutomatic coverage: this repo's
ci.ymlrunsnpm test. That includes__tests__/backends/prism-proxy.test.ts, which runs the emitted script against a stand-in for Prism and checks four things:The emitter tests check that both setups launch the proxy and that the proxy is omitted when there are no REST operations. The contract suites run in each SDK repo's CI on its regeneration PR, after a generator release.
Integration matrix:
name[]=name[]=Fidelity: Prism and the generated clients run for real, and Prism returns mock responses instead of calling Platform.
Not proven here:
tags_test.exsin firstlanding covers the single-valuetags[]=form.Known limitations
tags=xstill passes. From reading the code, Go, Swift and Elixir send that form. The proxy could reject bare array names by reading the spec, but that would fail those SDKs until they're fixed, so it's a follow-up.Follow-ups
🤖 Generated with Claude Code