Repository navigation
fix(http-client-js): serialize form-urlencoded bodies with URLSearchParams - #12412
Joel Shearon (hippi345) wants to merge 3 commits into
Conversation
…arams Request bodies with content type application/x-www-form-urlencoded were sent through the JSON transport transform. Encode those model and record bodies with URLSearchParams instead.
|
Azure Pipelines: Successfully started running 1 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
🟡 Changes recommended
Nullable form bodies still bypass encoding, and form-specific field names are mishandled for named models and parameterized content types.
3 open issues
What changed in this PR
Fixes #12349 by adding URL-encoded request-body serialization to the JavaScript HTTP client emitter instead of sending JSON under a form content type.
Changes:
- Adds a conditional
URLSearchParamshelper that skips absent values, repeats array keys, and JSON-encodes nested objects. - Routes model and record form bodies through the helper.
- Adds emitter scenarios and a changelog entry.
| File | Description |
|---|---|
packages/http-client-js/test/scenarios/http-operations/form-urlencoded-body.md |
Adds record and model form-body scenarios. |
packages/http-client-js/src/utils/form-urlencoded.ts |
Detects form content types, including parameters. |
packages/http-client-js/src/emitter.tsx |
Registers conditional form-helper emission. |
packages/http-client-js/src/components/transforms/operation-transform-expression.tsx |
Wraps form-body transforms with the encoder. |
packages/http-client-js/src/components/static-helpers/form-urlencoded.tsx |
Generates the form encoder when needed. |
packages/http-client-js/src/components/index.ts |
Exports the helper component. |
.chronus/changes/fix-12349-form-urlencoded-2026-9-27-19-55-38.md |
Records the serialization fix. |
Review effort: Balanced
| const payloadType = body.type; | ||
| if ( | ||
| body.bodyKind === "single" && | ||
| payloadType.kind === "Model" && |
| }} | ||
| > | ||
| {code`${getEncodeFormUrlEncodedRef()}(${( | ||
| <JsonTransform itemRef={itemRef} target="transport" type={payloadType} /> |
Recognize nullable model form bodies, use canonical form media type for encoded names, and emit form-specific transport serializers for models shared with JSON operations.
There was a problem hiding this comment.
🟡 Changes recommended
Form serializer traversal and dispatch defects leave generated client references unresolved and produce incorrect property names or scalar encodings for nullable and discriminated models.
6 open issues
Apply form serialization to non-null union variants · New Exclude unnamed models from form serializer declarations · New Recurse into indexed values when collecting form serializers · New Propagate form media type through discriminator serializers · New Generate form-specific serializers for named body models Handle nullable model unions in form-body encoding
1 resolved since last review
Review effort: Balanced
| type={payloadType} | ||
| serializationMediaType={FORM_URL_ENCODED_MEDIA_TYPE} |
| } | ||
|
|
||
| if ($.model.is(payloadType)) { | ||
| if (typeof payloadType.name === "string") { |
| for (const property of $.model | ||
| .getProperties(payloadType, { includeExtended: true }) | ||
| .values()) { | ||
| collectNamedTypesForFormSerialization($, unpackProperty(property), result, visited); | ||
| } |
| const serializationMediaType = | ||
| props.serializerKind === "form_urlencoded" ? "application/x-www-form-urlencoded" : undefined; |
There was a problem hiding this comment.
🟡 Changes recommended
Critical form-serialization defects generate unresolved type or serializer references and incorrect field names for nullable and discriminated models.
8 open issues
Propagate form serialization through discriminator dispatch · New Serialize non-null model branches of nullable unions · New Recurse into indexed values when collecting form serializers Exclude unnamed models from form serializer declarations Apply form serialization to non-null union variants Propagate form media type through discriminator serializers Generate form-specific serializers for named body models Handle nullable model unions in form-body encoding
Review effort: Balanced
| <JsonTransformDeclaration | ||
| type={type} | ||
| target="transport" | ||
| serializerKind="form_urlencoded" |
| <JsonTransform | ||
| itemRef={itemRef} | ||
| target="transport" | ||
| type={payloadType} | ||
| serializationMediaType={FORM_URL_ENCODED_MEDIA_TYPE} |


Summary
Fixes #12349.
@typespec/http-client-jssentapplication/x-www-form-urlencodedrequest bodies through the JSON transport transform, so the runtime posted JSON under a form content type. Those model and record bodies are now encoded withURLSearchParams.The generated
encodeFormUrlEncodedhelper skips null and undefined values, repeats keys for arrays, and JSON-encodes nested objects. Emitter scenarios cover aRecord<string>body and a model body.Test plan
pnpm --filter @typespec/http-client-js buildpnpm --filter @typespec/http-client-js testpnpm --filter @typespec/http-client-js lint