From c488be5f1220b3072bed1ead61261dc97775c973 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 02:40:20 +0000 Subject: [PATCH] Update all examples and snapshots with FormData fix Co-authored-by: mrlubos <12529395+mrlubos@users.noreply.github.com> --- .../src/client/client/client.gen.ts | 17 +++++++++++++++-- .../base-url-false/client/client.gen.ts | 17 +++++++++++++++-- .../base-url-number/client/client.gen.ts | 17 +++++++++++++++-- .../base-url-strict/client/client.gen.ts | 17 +++++++++++++++-- .../base-url-string/client/client.gen.ts | 17 +++++++++++++++-- .../clean-false/client/client.gen.ts | 17 +++++++++++++++-- .../client-ofetch/default/client/client.gen.ts | 17 +++++++++++++++-- .../client/client.gen.ts | 17 +++++++++++++++-- .../sdk-client-optional/client/client.gen.ts | 17 +++++++++++++++-- .../sdk-client-required/client/client.gen.ts | 17 +++++++++++++++-- .../tsconfig-nodenext-sdk/client/client.gen.ts | 17 +++++++++++++++-- .../3.1.x/sse-ofetch/client/client.gen.ts | 17 +++++++++++++++-- 12 files changed, 180 insertions(+), 24 deletions(-) diff --git a/examples/openapi-ts-ofetch/src/client/client/client.gen.ts b/examples/openapi-ts-ofetch/src/client/client/client.gen.ts index e0e3c2a41..66fae47f7 100644 --- a/examples/openapi-ts-ofetch/src/client/client/client.gen.ts +++ b/examples/openapi-ts-ofetch/src/client/client/client.gen.ts @@ -125,6 +125,7 @@ export const createClient = (config: Config = {}): Client => { const applyRequestInterceptors = async ( request: Request, opts: ResolvedRequestOptions, + body: BodyInit | null | undefined, ) => { for (const fn of interceptors.request.fns) { if (fn) { @@ -138,6 +139,18 @@ export const createClient = (config: Config = {}): Client => { // body comes only from getValidRequestBody(options) // reflect signal if present opts.signal = (request as any).signal as AbortSignal | undefined; + + // When body is FormData, remove Content-Type header to avoid boundary mismatch. + // Note: We already delete Content-Type in resolveOptions for FormData, but the + // Request constructor (line 175) re-adds it with an auto-generated boundary. + // Since we pass the original FormData (not the Request's body) to ofetch, and + // ofetch will generate its own boundary, we must remove the Request's Content-Type + // to let ofetch set the correct one. Otherwise the boundary in the header won't + // match the boundary in the actual multipart body sent by ofetch. + if (typeof FormData !== 'undefined' && body instanceof FormData) { + opts.headers.delete('Content-Type'); + } + return request; }; @@ -176,7 +189,7 @@ export const createClient = (config: Config = {}): Client => { }; let request = new Request(url, requestInit); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); const finalUrl = request.url; // build ofetch options and perform the request (.raw keeps the Response) @@ -235,7 +248,7 @@ export const createClient = (config: Config = {}): Client => { method, onRequest: async (url, init) => { let request = new Request(url, init); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); return request; }, serializedBody: networkBody as BodyInit | null | undefined, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-false/client/client.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-false/client/client.gen.ts index e0e3c2a41..66fae47f7 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-false/client/client.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-false/client/client.gen.ts @@ -125,6 +125,7 @@ export const createClient = (config: Config = {}): Client => { const applyRequestInterceptors = async ( request: Request, opts: ResolvedRequestOptions, + body: BodyInit | null | undefined, ) => { for (const fn of interceptors.request.fns) { if (fn) { @@ -138,6 +139,18 @@ export const createClient = (config: Config = {}): Client => { // body comes only from getValidRequestBody(options) // reflect signal if present opts.signal = (request as any).signal as AbortSignal | undefined; + + // When body is FormData, remove Content-Type header to avoid boundary mismatch. + // Note: We already delete Content-Type in resolveOptions for FormData, but the + // Request constructor (line 175) re-adds it with an auto-generated boundary. + // Since we pass the original FormData (not the Request's body) to ofetch, and + // ofetch will generate its own boundary, we must remove the Request's Content-Type + // to let ofetch set the correct one. Otherwise the boundary in the header won't + // match the boundary in the actual multipart body sent by ofetch. + if (typeof FormData !== 'undefined' && body instanceof FormData) { + opts.headers.delete('Content-Type'); + } + return request; }; @@ -176,7 +189,7 @@ export const createClient = (config: Config = {}): Client => { }; let request = new Request(url, requestInit); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); const finalUrl = request.url; // build ofetch options and perform the request (.raw keeps the Response) @@ -235,7 +248,7 @@ export const createClient = (config: Config = {}): Client => { method, onRequest: async (url, init) => { let request = new Request(url, init); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); return request; }, serializedBody: networkBody as BodyInit | null | undefined, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-number/client/client.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-number/client/client.gen.ts index e0e3c2a41..66fae47f7 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-number/client/client.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-number/client/client.gen.ts @@ -125,6 +125,7 @@ export const createClient = (config: Config = {}): Client => { const applyRequestInterceptors = async ( request: Request, opts: ResolvedRequestOptions, + body: BodyInit | null | undefined, ) => { for (const fn of interceptors.request.fns) { if (fn) { @@ -138,6 +139,18 @@ export const createClient = (config: Config = {}): Client => { // body comes only from getValidRequestBody(options) // reflect signal if present opts.signal = (request as any).signal as AbortSignal | undefined; + + // When body is FormData, remove Content-Type header to avoid boundary mismatch. + // Note: We already delete Content-Type in resolveOptions for FormData, but the + // Request constructor (line 175) re-adds it with an auto-generated boundary. + // Since we pass the original FormData (not the Request's body) to ofetch, and + // ofetch will generate its own boundary, we must remove the Request's Content-Type + // to let ofetch set the correct one. Otherwise the boundary in the header won't + // match the boundary in the actual multipart body sent by ofetch. + if (typeof FormData !== 'undefined' && body instanceof FormData) { + opts.headers.delete('Content-Type'); + } + return request; }; @@ -176,7 +189,7 @@ export const createClient = (config: Config = {}): Client => { }; let request = new Request(url, requestInit); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); const finalUrl = request.url; // build ofetch options and perform the request (.raw keeps the Response) @@ -235,7 +248,7 @@ export const createClient = (config: Config = {}): Client => { method, onRequest: async (url, init) => { let request = new Request(url, init); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); return request; }, serializedBody: networkBody as BodyInit | null | undefined, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-strict/client/client.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-strict/client/client.gen.ts index e0e3c2a41..66fae47f7 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-strict/client/client.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-strict/client/client.gen.ts @@ -125,6 +125,7 @@ export const createClient = (config: Config = {}): Client => { const applyRequestInterceptors = async ( request: Request, opts: ResolvedRequestOptions, + body: BodyInit | null | undefined, ) => { for (const fn of interceptors.request.fns) { if (fn) { @@ -138,6 +139,18 @@ export const createClient = (config: Config = {}): Client => { // body comes only from getValidRequestBody(options) // reflect signal if present opts.signal = (request as any).signal as AbortSignal | undefined; + + // When body is FormData, remove Content-Type header to avoid boundary mismatch. + // Note: We already delete Content-Type in resolveOptions for FormData, but the + // Request constructor (line 175) re-adds it with an auto-generated boundary. + // Since we pass the original FormData (not the Request's body) to ofetch, and + // ofetch will generate its own boundary, we must remove the Request's Content-Type + // to let ofetch set the correct one. Otherwise the boundary in the header won't + // match the boundary in the actual multipart body sent by ofetch. + if (typeof FormData !== 'undefined' && body instanceof FormData) { + opts.headers.delete('Content-Type'); + } + return request; }; @@ -176,7 +189,7 @@ export const createClient = (config: Config = {}): Client => { }; let request = new Request(url, requestInit); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); const finalUrl = request.url; // build ofetch options and perform the request (.raw keeps the Response) @@ -235,7 +248,7 @@ export const createClient = (config: Config = {}): Client => { method, onRequest: async (url, init) => { let request = new Request(url, init); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); return request; }, serializedBody: networkBody as BodyInit | null | undefined, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-string/client/client.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-string/client/client.gen.ts index e0e3c2a41..66fae47f7 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-string/client/client.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/base-url-string/client/client.gen.ts @@ -125,6 +125,7 @@ export const createClient = (config: Config = {}): Client => { const applyRequestInterceptors = async ( request: Request, opts: ResolvedRequestOptions, + body: BodyInit | null | undefined, ) => { for (const fn of interceptors.request.fns) { if (fn) { @@ -138,6 +139,18 @@ export const createClient = (config: Config = {}): Client => { // body comes only from getValidRequestBody(options) // reflect signal if present opts.signal = (request as any).signal as AbortSignal | undefined; + + // When body is FormData, remove Content-Type header to avoid boundary mismatch. + // Note: We already delete Content-Type in resolveOptions for FormData, but the + // Request constructor (line 175) re-adds it with an auto-generated boundary. + // Since we pass the original FormData (not the Request's body) to ofetch, and + // ofetch will generate its own boundary, we must remove the Request's Content-Type + // to let ofetch set the correct one. Otherwise the boundary in the header won't + // match the boundary in the actual multipart body sent by ofetch. + if (typeof FormData !== 'undefined' && body instanceof FormData) { + opts.headers.delete('Content-Type'); + } + return request; }; @@ -176,7 +189,7 @@ export const createClient = (config: Config = {}): Client => { }; let request = new Request(url, requestInit); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); const finalUrl = request.url; // build ofetch options and perform the request (.raw keeps the Response) @@ -235,7 +248,7 @@ export const createClient = (config: Config = {}): Client => { method, onRequest: async (url, init) => { let request = new Request(url, init); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); return request; }, serializedBody: networkBody as BodyInit | null | undefined, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/clean-false/client/client.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/clean-false/client/client.gen.ts index e0e3c2a41..66fae47f7 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/clean-false/client/client.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/clean-false/client/client.gen.ts @@ -125,6 +125,7 @@ export const createClient = (config: Config = {}): Client => { const applyRequestInterceptors = async ( request: Request, opts: ResolvedRequestOptions, + body: BodyInit | null | undefined, ) => { for (const fn of interceptors.request.fns) { if (fn) { @@ -138,6 +139,18 @@ export const createClient = (config: Config = {}): Client => { // body comes only from getValidRequestBody(options) // reflect signal if present opts.signal = (request as any).signal as AbortSignal | undefined; + + // When body is FormData, remove Content-Type header to avoid boundary mismatch. + // Note: We already delete Content-Type in resolveOptions for FormData, but the + // Request constructor (line 175) re-adds it with an auto-generated boundary. + // Since we pass the original FormData (not the Request's body) to ofetch, and + // ofetch will generate its own boundary, we must remove the Request's Content-Type + // to let ofetch set the correct one. Otherwise the boundary in the header won't + // match the boundary in the actual multipart body sent by ofetch. + if (typeof FormData !== 'undefined' && body instanceof FormData) { + opts.headers.delete('Content-Type'); + } + return request; }; @@ -176,7 +189,7 @@ export const createClient = (config: Config = {}): Client => { }; let request = new Request(url, requestInit); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); const finalUrl = request.url; // build ofetch options and perform the request (.raw keeps the Response) @@ -235,7 +248,7 @@ export const createClient = (config: Config = {}): Client => { method, onRequest: async (url, init) => { let request = new Request(url, init); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); return request; }, serializedBody: networkBody as BodyInit | null | undefined, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/default/client/client.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/default/client/client.gen.ts index e0e3c2a41..66fae47f7 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/default/client/client.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/default/client/client.gen.ts @@ -125,6 +125,7 @@ export const createClient = (config: Config = {}): Client => { const applyRequestInterceptors = async ( request: Request, opts: ResolvedRequestOptions, + body: BodyInit | null | undefined, ) => { for (const fn of interceptors.request.fns) { if (fn) { @@ -138,6 +139,18 @@ export const createClient = (config: Config = {}): Client => { // body comes only from getValidRequestBody(options) // reflect signal if present opts.signal = (request as any).signal as AbortSignal | undefined; + + // When body is FormData, remove Content-Type header to avoid boundary mismatch. + // Note: We already delete Content-Type in resolveOptions for FormData, but the + // Request constructor (line 175) re-adds it with an auto-generated boundary. + // Since we pass the original FormData (not the Request's body) to ofetch, and + // ofetch will generate its own boundary, we must remove the Request's Content-Type + // to let ofetch set the correct one. Otherwise the boundary in the header won't + // match the boundary in the actual multipart body sent by ofetch. + if (typeof FormData !== 'undefined' && body instanceof FormData) { + opts.headers.delete('Content-Type'); + } + return request; }; @@ -176,7 +189,7 @@ export const createClient = (config: Config = {}): Client => { }; let request = new Request(url, requestInit); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); const finalUrl = request.url; // build ofetch options and perform the request (.raw keeps the Response) @@ -235,7 +248,7 @@ export const createClient = (config: Config = {}): Client => { method, onRequest: async (url, init) => { let request = new Request(url, init); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); return request; }, serializedBody: networkBody as BodyInit | null | undefined, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/import-file-extension-ts/client/client.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/import-file-extension-ts/client/client.gen.ts index 952a4d0c2..ebee86e7a 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/import-file-extension-ts/client/client.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/import-file-extension-ts/client/client.gen.ts @@ -125,6 +125,7 @@ export const createClient = (config: Config = {}): Client => { const applyRequestInterceptors = async ( request: Request, opts: ResolvedRequestOptions, + body: BodyInit | null | undefined, ) => { for (const fn of interceptors.request.fns) { if (fn) { @@ -138,6 +139,18 @@ export const createClient = (config: Config = {}): Client => { // body comes only from getValidRequestBody(options) // reflect signal if present opts.signal = (request as any).signal as AbortSignal | undefined; + + // When body is FormData, remove Content-Type header to avoid boundary mismatch. + // Note: We already delete Content-Type in resolveOptions for FormData, but the + // Request constructor (line 175) re-adds it with an auto-generated boundary. + // Since we pass the original FormData (not the Request's body) to ofetch, and + // ofetch will generate its own boundary, we must remove the Request's Content-Type + // to let ofetch set the correct one. Otherwise the boundary in the header won't + // match the boundary in the actual multipart body sent by ofetch. + if (typeof FormData !== 'undefined' && body instanceof FormData) { + opts.headers.delete('Content-Type'); + } + return request; }; @@ -176,7 +189,7 @@ export const createClient = (config: Config = {}): Client => { }; let request = new Request(url, requestInit); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); const finalUrl = request.url; // build ofetch options and perform the request (.raw keeps the Response) @@ -235,7 +248,7 @@ export const createClient = (config: Config = {}): Client => { method, onRequest: async (url, init) => { let request = new Request(url, init); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); return request; }, serializedBody: networkBody as BodyInit | null | undefined, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/sdk-client-optional/client/client.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/sdk-client-optional/client/client.gen.ts index e0e3c2a41..66fae47f7 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/sdk-client-optional/client/client.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/sdk-client-optional/client/client.gen.ts @@ -125,6 +125,7 @@ export const createClient = (config: Config = {}): Client => { const applyRequestInterceptors = async ( request: Request, opts: ResolvedRequestOptions, + body: BodyInit | null | undefined, ) => { for (const fn of interceptors.request.fns) { if (fn) { @@ -138,6 +139,18 @@ export const createClient = (config: Config = {}): Client => { // body comes only from getValidRequestBody(options) // reflect signal if present opts.signal = (request as any).signal as AbortSignal | undefined; + + // When body is FormData, remove Content-Type header to avoid boundary mismatch. + // Note: We already delete Content-Type in resolveOptions for FormData, but the + // Request constructor (line 175) re-adds it with an auto-generated boundary. + // Since we pass the original FormData (not the Request's body) to ofetch, and + // ofetch will generate its own boundary, we must remove the Request's Content-Type + // to let ofetch set the correct one. Otherwise the boundary in the header won't + // match the boundary in the actual multipart body sent by ofetch. + if (typeof FormData !== 'undefined' && body instanceof FormData) { + opts.headers.delete('Content-Type'); + } + return request; }; @@ -176,7 +189,7 @@ export const createClient = (config: Config = {}): Client => { }; let request = new Request(url, requestInit); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); const finalUrl = request.url; // build ofetch options and perform the request (.raw keeps the Response) @@ -235,7 +248,7 @@ export const createClient = (config: Config = {}): Client => { method, onRequest: async (url, init) => { let request = new Request(url, init); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); return request; }, serializedBody: networkBody as BodyInit | null | undefined, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/sdk-client-required/client/client.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/sdk-client-required/client/client.gen.ts index e0e3c2a41..66fae47f7 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/sdk-client-required/client/client.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/sdk-client-required/client/client.gen.ts @@ -125,6 +125,7 @@ export const createClient = (config: Config = {}): Client => { const applyRequestInterceptors = async ( request: Request, opts: ResolvedRequestOptions, + body: BodyInit | null | undefined, ) => { for (const fn of interceptors.request.fns) { if (fn) { @@ -138,6 +139,18 @@ export const createClient = (config: Config = {}): Client => { // body comes only from getValidRequestBody(options) // reflect signal if present opts.signal = (request as any).signal as AbortSignal | undefined; + + // When body is FormData, remove Content-Type header to avoid boundary mismatch. + // Note: We already delete Content-Type in resolveOptions for FormData, but the + // Request constructor (line 175) re-adds it with an auto-generated boundary. + // Since we pass the original FormData (not the Request's body) to ofetch, and + // ofetch will generate its own boundary, we must remove the Request's Content-Type + // to let ofetch set the correct one. Otherwise the boundary in the header won't + // match the boundary in the actual multipart body sent by ofetch. + if (typeof FormData !== 'undefined' && body instanceof FormData) { + opts.headers.delete('Content-Type'); + } + return request; }; @@ -176,7 +189,7 @@ export const createClient = (config: Config = {}): Client => { }; let request = new Request(url, requestInit); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); const finalUrl = request.url; // build ofetch options and perform the request (.raw keeps the Response) @@ -235,7 +248,7 @@ export const createClient = (config: Config = {}): Client => { method, onRequest: async (url, init) => { let request = new Request(url, init); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); return request; }, serializedBody: networkBody as BodyInit | null | undefined, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/tsconfig-nodenext-sdk/client/client.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/tsconfig-nodenext-sdk/client/client.gen.ts index 3e1cf2053..8798e2a0e 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/tsconfig-nodenext-sdk/client/client.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/clients/@hey-api/client-ofetch/tsconfig-nodenext-sdk/client/client.gen.ts @@ -125,6 +125,7 @@ export const createClient = (config: Config = {}): Client => { const applyRequestInterceptors = async ( request: Request, opts: ResolvedRequestOptions, + body: BodyInit | null | undefined, ) => { for (const fn of interceptors.request.fns) { if (fn) { @@ -138,6 +139,18 @@ export const createClient = (config: Config = {}): Client => { // body comes only from getValidRequestBody(options) // reflect signal if present opts.signal = (request as any).signal as AbortSignal | undefined; + + // When body is FormData, remove Content-Type header to avoid boundary mismatch. + // Note: We already delete Content-Type in resolveOptions for FormData, but the + // Request constructor (line 175) re-adds it with an auto-generated boundary. + // Since we pass the original FormData (not the Request's body) to ofetch, and + // ofetch will generate its own boundary, we must remove the Request's Content-Type + // to let ofetch set the correct one. Otherwise the boundary in the header won't + // match the boundary in the actual multipart body sent by ofetch. + if (typeof FormData !== 'undefined' && body instanceof FormData) { + opts.headers.delete('Content-Type'); + } + return request; }; @@ -176,7 +189,7 @@ export const createClient = (config: Config = {}): Client => { }; let request = new Request(url, requestInit); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); const finalUrl = request.url; // build ofetch options and perform the request (.raw keeps the Response) @@ -235,7 +248,7 @@ export const createClient = (config: Config = {}): Client => { method, onRequest: async (url, init) => { let request = new Request(url, init); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); return request; }, serializedBody: networkBody as BodyInit | null | undefined, diff --git a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/sse-ofetch/client/client.gen.ts b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/sse-ofetch/client/client.gen.ts index e0e3c2a41..66fae47f7 100644 --- a/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/sse-ofetch/client/client.gen.ts +++ b/packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/sse-ofetch/client/client.gen.ts @@ -125,6 +125,7 @@ export const createClient = (config: Config = {}): Client => { const applyRequestInterceptors = async ( request: Request, opts: ResolvedRequestOptions, + body: BodyInit | null | undefined, ) => { for (const fn of interceptors.request.fns) { if (fn) { @@ -138,6 +139,18 @@ export const createClient = (config: Config = {}): Client => { // body comes only from getValidRequestBody(options) // reflect signal if present opts.signal = (request as any).signal as AbortSignal | undefined; + + // When body is FormData, remove Content-Type header to avoid boundary mismatch. + // Note: We already delete Content-Type in resolveOptions for FormData, but the + // Request constructor (line 175) re-adds it with an auto-generated boundary. + // Since we pass the original FormData (not the Request's body) to ofetch, and + // ofetch will generate its own boundary, we must remove the Request's Content-Type + // to let ofetch set the correct one. Otherwise the boundary in the header won't + // match the boundary in the actual multipart body sent by ofetch. + if (typeof FormData !== 'undefined' && body instanceof FormData) { + opts.headers.delete('Content-Type'); + } + return request; }; @@ -176,7 +189,7 @@ export const createClient = (config: Config = {}): Client => { }; let request = new Request(url, requestInit); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); const finalUrl = request.url; // build ofetch options and perform the request (.raw keeps the Response) @@ -235,7 +248,7 @@ export const createClient = (config: Config = {}): Client => { method, onRequest: async (url, init) => { let request = new Request(url, init); - request = await applyRequestInterceptors(request, opts); + request = await applyRequestInterceptors(request, opts, networkBody); return request; }, serializedBody: networkBody as BodyInit | null | undefined, -- 2.51.2