Skip to content

Commit 929bfb9

Browse files
committed
fix: adjust handling of exploded arrays with deepObject style to match stripe
1 parent 52b8709 commit 929bfb9

2 files changed

Lines changed: 34 additions & 12 deletions

File tree

packages/typescript-fetch-runtime/src/request-bodies/url-search-param.spec.ts

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ describe("typescript-fetch-runtime/request-bodies/requestBodyToUrlSearchParams",
1717
)
1818

1919
expect(actual.toString()).toStrictEqual(
20+
// todo: original example from oas differs, https://github.com/OAI/OpenAPI-Specification/issues/4813
2021
"id=f81d4fae-7dec-11d0-a765-00a0c91e6bf6&address=%7B%22streetAddress%22%3A%22123+Example+Dr.%22%2C%22city%22%3A%22Somewhere%22%2C%22state%22%3A%22CA%22%2C%22zip%22%3A%2299999%2B1234%22%7D",
2122
)
2223
})
@@ -33,10 +34,11 @@ describe("typescript-fetch-runtime/request-bodies/requestBodyToUrlSearchParams",
3334
explode: false,
3435
style: "form",
3536
string: "color=blue",
36-
// TODO: is it correct to url encode these?
3737
array: "color=blue%2Cblack%2Cbrown",
38+
// todo: original example from oas differs, https://github.com/OAI/OpenAPI-Specification/issues/4813
3839
// array: "color=blue,black,brown",
3940
object: "color=R%2C100%2CG%2C200%2CB%2C150",
41+
// todo: original example from oas differs, https://github.com/OAI/OpenAPI-Specification/issues/4813
4042
// object: "color=R,100,G,200,B,150",
4143
},
4244
{
@@ -54,17 +56,11 @@ describe("typescript-fetch-runtime/request-bodies/requestBodyToUrlSearchParams",
5456
style: "spaceDelimited",
5557
// note: undefined by spec
5658
string: "color=blue",
57-
// TODO: is it correct to use + for spaces here?
58-
// RFC 1866 suggests yes:
59-
// "The form field names and values are escaped: space
60-
// characters are replaced by `+', and then reserved characters
61-
// are escaped as per [URL]; that is, non-alphanumeric
62-
// characters are replaced by `%HH', a percent sign and two
63-
// hexadecimal digits representing the ASCII code of the
64-
// character."
6559
array: "color=blue+black+brown",
60+
// todo: original example from oas differs, https://github.com/OAI/OpenAPI-Specification/issues/4813
6661
// array: "color=blue%20black%20brown",
6762
object: "color=R+100+G+200+B+150",
63+
// todo: original example from oas differs, https://github.com/OAI/OpenAPI-Specification/issues/4813
6864
// object: "color=R%20100%20G%20200%20B%20150",
6965
},
7066
{
@@ -90,8 +86,8 @@ describe("typescript-fetch-runtime/request-bodies/requestBodyToUrlSearchParams",
9086
style: "deepObject",
9187
// note: undefined by spec
9288
string: "color=blue",
93-
// note: undefined by spec
94-
array: "color=blue&color=black&color=brown",
89+
// note: undefined by spec; using stripe expectation of `color[0]=blue&color[1]=black&color[2]=brown`
90+
array: "color%5B0%5D=blue&color%5B1%5D=black&color%5B2%5D=brown",
9591
object: "color%5BR%5D=100&color%5BG%5D=200&color%5BB%5D=150",
9692
},
9793
{
@@ -138,7 +134,13 @@ describe("typescript-fetch-runtime/request-bodies/requestBodyToUrlSearchParams",
138134
},
139135
)
140136

141-
describe("stripe style: 'deepObject' explode: true", () => {
137+
describe("stripe /v1 api conventions; style: 'deepObject' explode: true", () => {
138+
/**
139+
* conventions based on the way the stripe nodejs sdk is implemented at time of writing,
140+
* https://github.com/stripe/stripe-node/blob/67b2f17c813bef59635baa6d8b3f246a8c355431/src/utils.ts#L53-L69
141+
* excluding their use of raw `[` / `]` characters rather than percent-encoded brackets.
142+
*/
143+
142144
it("serializes a nested object correctly", () => {
143145
const actual = requestBodyToUrlSearchParams(
144146
{
@@ -163,5 +165,21 @@ describe("typescript-fetch-runtime/request-bodies/requestBodyToUrlSearchParams",
163165
"components%5Baccount%5D%5Benabled%5D=true&components%5Baccount%5D%5Bfeatures%5D%5Bsome_flag%5D=false&components%5Baccount%5D%5Bfeatures%5D%5Bsome_other_flag%5D=true",
164166
)
165167
})
168+
169+
it("serializes a nested array correctly", () => {
170+
const actual = requestBodyToUrlSearchParams(
171+
{
172+
arr: ["red", "blue"],
173+
},
174+
{
175+
arr: {
176+
explode: true,
177+
style: "deepObject",
178+
},
179+
},
180+
)
181+
182+
expect(actual.toString()).toStrictEqual("arr%5B0%5D=red&arr%5B1%5D=blue")
183+
})
166184
})
167185
})

packages/typescript-fetch-runtime/src/request-bodies/url-search-params.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ function addArrayValue(
3030
value: unknown[],
3131
encoding: Required<Encoding>,
3232
) {
33+
if (encoding.style === "deepObject" && encoding.explode) {
34+
return addObjectValue(result, key, value, encoding)
35+
}
36+
3337
if (encoding.explode) {
3438
for (const it of value) {
3539
result.append(key, String(it))

0 commit comments

Comments
 (0)