Skip to content

Conversation

@mnahkies
Copy link
Owner

@mnahkies mnahkies commented Jul 23, 2025

adds support for application/x-www-form-urlencoded request bodies, including the encoding property to customize the serialization of object and array values.

it's implemented for typescript-fetch and typescript-axios with partial support on the server templates (they don't currently understand encoding, so its a bit of pot-luck whether they'll accurately de-serialize the data)

later we'll extract some of the duplicated code into a new core runtime package, as there's an increasingly large body of code that is shared between the different runtimes.

additionally improves handling of optional request bodies, particularly in the case that the consuming project has exactOptionalPropertyTypes enabled. This is currently more correct on the typescript-fetch template, due to some quirks of axios - see skipped e2e tests for details.

import {ClientServersBuilder} from "./client-servers-builder"

export abstract class AbstractClientBuilder implements ICompilable {
protected abstract readonly capabilities: {
Copy link
Owner Author

Choose a reason for hiding this comment

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

Rudimentary capabilities concept to more easily allow for skew of feature parity between templates

style: "spaceDelimited",
// note: undefined by spec
string: "color=blue",
// TODO: is it correct to use + for spaces here?
Copy link
Owner Author

Choose a reason for hiding this comment

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

There's several test cases here using examples form the OAI specification that don't agree. I've opened OAI/OpenAPI-Specification#4813 to discuss

},
)

describe("stripe /v1 api conventions; style: 'deepObject' explode: true", () => {
Copy link
Owner Author

Choose a reason for hiding this comment

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

Where behavior is otherwise undefined in terms of OAI, I've aligned to what the stripe v1 API does/expects. It's a popular API, the only example of nested objects/arrays I have right now.

@mnahkies mnahkies force-pushed the mn/feat/support-urlencoded-request-bodies branch from 1ec1c0a to 0449e27 Compare July 25, 2025 14:06

const queryString = builder.queryString()
const headers = builder.headers()
const headers = builder.headers({nullContentTypeValue: "false"})
Copy link
Owner Author

Choose a reason for hiding this comment

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

Turns out that axios will always send a Content-Type header with POST requests, even if there isn't a body. This then ends up being parsed by the receiving server erroneously.

Setting the Content-Type header to false is the only way I've found to drop this behavior 😢 (it then omits the header completely, setting to null or undefined don't work)

https://axios-http.com/docs/config_defaults

return serialize
}

return `${param} !== undefined ? ${serialize} : null`
Copy link
Owner Author

Choose a reason for hiding this comment

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

Avoids issues with exact optional types compiler option - RequestInit defines body?: T | null so undefined isn't accepted with exactOptionalPropertyTypes

return headers
}

protected _requestBodyToUrlSearchParams(
Copy link
Owner Author

Choose a reason for hiding this comment

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

In two minds about this, but using a protected wrapping method leaves the door open to someone extending the client class and overriding it I guess

if (body !== "disabled") {
app.use(express.json(body?.json))
app.use(express.text(body?.text))
app.use(express.urlencoded(body?.urlencoded ?? {extended: true}))
Copy link
Owner Author

Choose a reason for hiding this comment

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

I'm starting to sense a future where we switch to using https://www.npmjs.com/package/raw-body by default for greater control over the parsing (being able to respect encoding properly)

Copy link
Owner Author

Choose a reason for hiding this comment

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

Duplicates the fetch runtime code for now - will introduce a shared package as a follow up

@mnahkies mnahkies force-pushed the mn/feat/support-urlencoded-request-bodies branch from d1a25a1 to ca58419 Compare July 26, 2025 11:25
@mnahkies mnahkies changed the title wip: feat: support urlencoded request bodies feat: support application/x-www-form-urlencoded request bodies Jul 26, 2025
@mnahkies mnahkies marked this pull request as ready for review July 26, 2025 11:25
@mnahkies mnahkies merged commit 0aecf2a into main Jul 26, 2025
6 checks passed
@mnahkies mnahkies deleted the mn/feat/support-urlencoded-request-bodies branch July 26, 2025 11:31
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.

2 participants