···125125 const applyRequestInterceptors = async (
126126 request: Request,
127127 opts: ResolvedRequestOptions,
128128+ body: BodyInit | null | undefined,
128129 ) => {
129130 for (const fn of interceptors.request.fns) {
130131 if (fn) {
···138139 // body comes only from getValidRequestBody(options)
139140 // reflect signal if present
140141 opts.signal = (request as any).signal as AbortSignal | undefined;
142142+143143+ // When body is FormData, remove Content-Type header to avoid boundary mismatch.
144144+ // Note: We already delete Content-Type in resolveOptions for FormData, but the
145145+ // Request constructor (line 175) re-adds it with an auto-generated boundary.
146146+ // Since we pass the original FormData (not the Request's body) to ofetch, and
147147+ // ofetch will generate its own boundary, we must remove the Request's Content-Type
148148+ // to let ofetch set the correct one. Otherwise the boundary in the header won't
149149+ // match the boundary in the actual multipart body sent by ofetch.
150150+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
151151+ opts.headers.delete('Content-Type');
152152+ }
153153+141154 return request;
142155 };
143156···176189 };
177190 let request = new Request(url, requestInit);
178191179179- request = await applyRequestInterceptors(request, opts);
192192+ request = await applyRequestInterceptors(request, opts, networkBody);
180193 const finalUrl = request.url;
181194182195 // build ofetch options and perform the request (.raw keeps the Response)
···235248 method,
236249 onRequest: async (url, init) => {
237250 let request = new Request(url, init);
238238- request = await applyRequestInterceptors(request, opts);
251251+ request = await applyRequestInterceptors(request, opts, networkBody);
239252 return request;
240253 },
241254 serializedBody: networkBody as BodyInit | null | undefined,
···125125 const applyRequestInterceptors = async (
126126 request: Request,
127127 opts: ResolvedRequestOptions,
128128+ body: BodyInit | null | undefined,
128129 ) => {
129130 for (const fn of interceptors.request.fns) {
130131 if (fn) {
···138139 // body comes only from getValidRequestBody(options)
139140 // reflect signal if present
140141 opts.signal = (request as any).signal as AbortSignal | undefined;
142142+143143+ // When body is FormData, remove Content-Type header to avoid boundary mismatch.
144144+ // Note: We already delete Content-Type in resolveOptions for FormData, but the
145145+ // Request constructor (line 175) re-adds it with an auto-generated boundary.
146146+ // Since we pass the original FormData (not the Request's body) to ofetch, and
147147+ // ofetch will generate its own boundary, we must remove the Request's Content-Type
148148+ // to let ofetch set the correct one. Otherwise the boundary in the header won't
149149+ // match the boundary in the actual multipart body sent by ofetch.
150150+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
151151+ opts.headers.delete('Content-Type');
152152+ }
153153+141154 return request;
142155 };
143156···176189 };
177190 let request = new Request(url, requestInit);
178191179179- request = await applyRequestInterceptors(request, opts);
192192+ request = await applyRequestInterceptors(request, opts, networkBody);
180193 const finalUrl = request.url;
181194182195 // build ofetch options and perform the request (.raw keeps the Response)
···235248 method,
236249 onRequest: async (url, init) => {
237250 let request = new Request(url, init);
238238- request = await applyRequestInterceptors(request, opts);
251251+ request = await applyRequestInterceptors(request, opts, networkBody);
239252 return request;
240253 },
241254 serializedBody: networkBody as BodyInit | null | undefined,
···125125 const applyRequestInterceptors = async (
126126 request: Request,
127127 opts: ResolvedRequestOptions,
128128+ body: BodyInit | null | undefined,
128129 ) => {
129130 for (const fn of interceptors.request.fns) {
130131 if (fn) {
···138139 // body comes only from getValidRequestBody(options)
139140 // reflect signal if present
140141 opts.signal = (request as any).signal as AbortSignal | undefined;
142142+143143+ // When body is FormData, remove Content-Type header to avoid boundary mismatch.
144144+ // Note: We already delete Content-Type in resolveOptions for FormData, but the
145145+ // Request constructor (line 175) re-adds it with an auto-generated boundary.
146146+ // Since we pass the original FormData (not the Request's body) to ofetch, and
147147+ // ofetch will generate its own boundary, we must remove the Request's Content-Type
148148+ // to let ofetch set the correct one. Otherwise the boundary in the header won't
149149+ // match the boundary in the actual multipart body sent by ofetch.
150150+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
151151+ opts.headers.delete('Content-Type');
152152+ }
153153+141154 return request;
142155 };
143156···176189 };
177190 let request = new Request(url, requestInit);
178191179179- request = await applyRequestInterceptors(request, opts);
192192+ request = await applyRequestInterceptors(request, opts, networkBody);
180193 const finalUrl = request.url;
181194182195 // build ofetch options and perform the request (.raw keeps the Response)
···235248 method,
236249 onRequest: async (url, init) => {
237250 let request = new Request(url, init);
238238- request = await applyRequestInterceptors(request, opts);
251251+ request = await applyRequestInterceptors(request, opts, networkBody);
239252 return request;
240253 },
241254 serializedBody: networkBody as BodyInit | null | undefined,
···125125 const applyRequestInterceptors = async (
126126 request: Request,
127127 opts: ResolvedRequestOptions,
128128+ body: BodyInit | null | undefined,
128129 ) => {
129130 for (const fn of interceptors.request.fns) {
130131 if (fn) {
···138139 // body comes only from getValidRequestBody(options)
139140 // reflect signal if present
140141 opts.signal = (request as any).signal as AbortSignal | undefined;
142142+143143+ // When body is FormData, remove Content-Type header to avoid boundary mismatch.
144144+ // Note: We already delete Content-Type in resolveOptions for FormData, but the
145145+ // Request constructor (line 175) re-adds it with an auto-generated boundary.
146146+ // Since we pass the original FormData (not the Request's body) to ofetch, and
147147+ // ofetch will generate its own boundary, we must remove the Request's Content-Type
148148+ // to let ofetch set the correct one. Otherwise the boundary in the header won't
149149+ // match the boundary in the actual multipart body sent by ofetch.
150150+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
151151+ opts.headers.delete('Content-Type');
152152+ }
153153+141154 return request;
142155 };
143156···176189 };
177190 let request = new Request(url, requestInit);
178191179179- request = await applyRequestInterceptors(request, opts);
192192+ request = await applyRequestInterceptors(request, opts, networkBody);
180193 const finalUrl = request.url;
181194182195 // build ofetch options and perform the request (.raw keeps the Response)
···235248 method,
236249 onRequest: async (url, init) => {
237250 let request = new Request(url, init);
238238- request = await applyRequestInterceptors(request, opts);
251251+ request = await applyRequestInterceptors(request, opts, networkBody);
239252 return request;
240253 },
241254 serializedBody: networkBody as BodyInit | null | undefined,
···125125 const applyRequestInterceptors = async (
126126 request: Request,
127127 opts: ResolvedRequestOptions,
128128+ body: BodyInit | null | undefined,
128129 ) => {
129130 for (const fn of interceptors.request.fns) {
130131 if (fn) {
···138139 // body comes only from getValidRequestBody(options)
139140 // reflect signal if present
140141 opts.signal = (request as any).signal as AbortSignal | undefined;
142142+143143+ // When body is FormData, remove Content-Type header to avoid boundary mismatch.
144144+ // Note: We already delete Content-Type in resolveOptions for FormData, but the
145145+ // Request constructor (line 175) re-adds it with an auto-generated boundary.
146146+ // Since we pass the original FormData (not the Request's body) to ofetch, and
147147+ // ofetch will generate its own boundary, we must remove the Request's Content-Type
148148+ // to let ofetch set the correct one. Otherwise the boundary in the header won't
149149+ // match the boundary in the actual multipart body sent by ofetch.
150150+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
151151+ opts.headers.delete('Content-Type');
152152+ }
153153+141154 return request;
142155 };
143156···176189 };
177190 let request = new Request(url, requestInit);
178191179179- request = await applyRequestInterceptors(request, opts);
192192+ request = await applyRequestInterceptors(request, opts, networkBody);
180193 const finalUrl = request.url;
181194182195 // build ofetch options and perform the request (.raw keeps the Response)
···235248 method,
236249 onRequest: async (url, init) => {
237250 let request = new Request(url, init);
238238- request = await applyRequestInterceptors(request, opts);
251251+ request = await applyRequestInterceptors(request, opts, networkBody);
239252 return request;
240253 },
241254 serializedBody: networkBody as BodyInit | null | undefined,
···125125 const applyRequestInterceptors = async (
126126 request: Request,
127127 opts: ResolvedRequestOptions,
128128+ body: BodyInit | null | undefined,
128129 ) => {
129130 for (const fn of interceptors.request.fns) {
130131 if (fn) {
···138139 // body comes only from getValidRequestBody(options)
139140 // reflect signal if present
140141 opts.signal = (request as any).signal as AbortSignal | undefined;
142142+143143+ // When body is FormData, remove Content-Type header to avoid boundary mismatch.
144144+ // Note: We already delete Content-Type in resolveOptions for FormData, but the
145145+ // Request constructor (line 175) re-adds it with an auto-generated boundary.
146146+ // Since we pass the original FormData (not the Request's body) to ofetch, and
147147+ // ofetch will generate its own boundary, we must remove the Request's Content-Type
148148+ // to let ofetch set the correct one. Otherwise the boundary in the header won't
149149+ // match the boundary in the actual multipart body sent by ofetch.
150150+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
151151+ opts.headers.delete('Content-Type');
152152+ }
153153+141154 return request;
142155 };
143156···176189 };
177190 let request = new Request(url, requestInit);
178191179179- request = await applyRequestInterceptors(request, opts);
192192+ request = await applyRequestInterceptors(request, opts, networkBody);
180193 const finalUrl = request.url;
181194182195 // build ofetch options and perform the request (.raw keeps the Response)
···235248 method,
236249 onRequest: async (url, init) => {
237250 let request = new Request(url, init);
238238- request = await applyRequestInterceptors(request, opts);
251251+ request = await applyRequestInterceptors(request, opts, networkBody);
239252 return request;
240253 },
241254 serializedBody: networkBody as BodyInit | null | undefined,
···125125 const applyRequestInterceptors = async (
126126 request: Request,
127127 opts: ResolvedRequestOptions,
128128+ body: BodyInit | null | undefined,
128129 ) => {
129130 for (const fn of interceptors.request.fns) {
130131 if (fn) {
···138139 // body comes only from getValidRequestBody(options)
139140 // reflect signal if present
140141 opts.signal = (request as any).signal as AbortSignal | undefined;
142142+143143+ // When body is FormData, remove Content-Type header to avoid boundary mismatch.
144144+ // Note: We already delete Content-Type in resolveOptions for FormData, but the
145145+ // Request constructor (line 175) re-adds it with an auto-generated boundary.
146146+ // Since we pass the original FormData (not the Request's body) to ofetch, and
147147+ // ofetch will generate its own boundary, we must remove the Request's Content-Type
148148+ // to let ofetch set the correct one. Otherwise the boundary in the header won't
149149+ // match the boundary in the actual multipart body sent by ofetch.
150150+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
151151+ opts.headers.delete('Content-Type');
152152+ }
153153+141154 return request;
142155 };
143156···176189 };
177190 let request = new Request(url, requestInit);
178191179179- request = await applyRequestInterceptors(request, opts);
192192+ request = await applyRequestInterceptors(request, opts, networkBody);
180193 const finalUrl = request.url;
181194182195 // build ofetch options and perform the request (.raw keeps the Response)
···235248 method,
236249 onRequest: async (url, init) => {
237250 let request = new Request(url, init);
238238- request = await applyRequestInterceptors(request, opts);
251251+ request = await applyRequestInterceptors(request, opts, networkBody);
239252 return request;
240253 },
241254 serializedBody: networkBody as BodyInit | null | undefined,
···125125 const applyRequestInterceptors = async (
126126 request: Request,
127127 opts: ResolvedRequestOptions,
128128+ body: BodyInit | null | undefined,
128129 ) => {
129130 for (const fn of interceptors.request.fns) {
130131 if (fn) {
···138139 // body comes only from getValidRequestBody(options)
139140 // reflect signal if present
140141 opts.signal = (request as any).signal as AbortSignal | undefined;
142142+143143+ // When body is FormData, remove Content-Type header to avoid boundary mismatch.
144144+ // Note: We already delete Content-Type in resolveOptions for FormData, but the
145145+ // Request constructor (line 175) re-adds it with an auto-generated boundary.
146146+ // Since we pass the original FormData (not the Request's body) to ofetch, and
147147+ // ofetch will generate its own boundary, we must remove the Request's Content-Type
148148+ // to let ofetch set the correct one. Otherwise the boundary in the header won't
149149+ // match the boundary in the actual multipart body sent by ofetch.
150150+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
151151+ opts.headers.delete('Content-Type');
152152+ }
153153+141154 return request;
142155 };
143156···176189 };
177190 let request = new Request(url, requestInit);
178191179179- request = await applyRequestInterceptors(request, opts);
192192+ request = await applyRequestInterceptors(request, opts, networkBody);
180193 const finalUrl = request.url;
181194182195 // build ofetch options and perform the request (.raw keeps the Response)
···235248 method,
236249 onRequest: async (url, init) => {
237250 let request = new Request(url, init);
238238- request = await applyRequestInterceptors(request, opts);
251251+ request = await applyRequestInterceptors(request, opts, networkBody);
239252 return request;
240253 },
241254 serializedBody: networkBody as BodyInit | null | undefined,
···125125 const applyRequestInterceptors = async (
126126 request: Request,
127127 opts: ResolvedRequestOptions,
128128+ body: BodyInit | null | undefined,
128129 ) => {
129130 for (const fn of interceptors.request.fns) {
130131 if (fn) {
···138139 // body comes only from getValidRequestBody(options)
139140 // reflect signal if present
140141 opts.signal = (request as any).signal as AbortSignal | undefined;
142142+143143+ // When body is FormData, remove Content-Type header to avoid boundary mismatch.
144144+ // Note: We already delete Content-Type in resolveOptions for FormData, but the
145145+ // Request constructor (line 175) re-adds it with an auto-generated boundary.
146146+ // Since we pass the original FormData (not the Request's body) to ofetch, and
147147+ // ofetch will generate its own boundary, we must remove the Request's Content-Type
148148+ // to let ofetch set the correct one. Otherwise the boundary in the header won't
149149+ // match the boundary in the actual multipart body sent by ofetch.
150150+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
151151+ opts.headers.delete('Content-Type');
152152+ }
153153+141154 return request;
142155 };
143156···176189 };
177190 let request = new Request(url, requestInit);
178191179179- request = await applyRequestInterceptors(request, opts);
192192+ request = await applyRequestInterceptors(request, opts, networkBody);
180193 const finalUrl = request.url;
181194182195 // build ofetch options and perform the request (.raw keeps the Response)
···235248 method,
236249 onRequest: async (url, init) => {
237250 let request = new Request(url, init);
238238- request = await applyRequestInterceptors(request, opts);
251251+ request = await applyRequestInterceptors(request, opts, networkBody);
239252 return request;
240253 },
241254 serializedBody: networkBody as BodyInit | null | undefined,
···125125 const applyRequestInterceptors = async (
126126 request: Request,
127127 opts: ResolvedRequestOptions,
128128+ body: BodyInit | null | undefined,
128129 ) => {
129130 for (const fn of interceptors.request.fns) {
130131 if (fn) {
···138139 // body comes only from getValidRequestBody(options)
139140 // reflect signal if present
140141 opts.signal = (request as any).signal as AbortSignal | undefined;
142142+143143+ // When body is FormData, remove Content-Type header to avoid boundary mismatch.
144144+ // Note: We already delete Content-Type in resolveOptions for FormData, but the
145145+ // Request constructor (line 175) re-adds it with an auto-generated boundary.
146146+ // Since we pass the original FormData (not the Request's body) to ofetch, and
147147+ // ofetch will generate its own boundary, we must remove the Request's Content-Type
148148+ // to let ofetch set the correct one. Otherwise the boundary in the header won't
149149+ // match the boundary in the actual multipart body sent by ofetch.
150150+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
151151+ opts.headers.delete('Content-Type');
152152+ }
153153+141154 return request;
142155 };
143156···176189 };
177190 let request = new Request(url, requestInit);
178191179179- request = await applyRequestInterceptors(request, opts);
192192+ request = await applyRequestInterceptors(request, opts, networkBody);
180193 const finalUrl = request.url;
181194182195 // build ofetch options and perform the request (.raw keeps the Response)
···235248 method,
236249 onRequest: async (url, init) => {
237250 let request = new Request(url, init);
238238- request = await applyRequestInterceptors(request, opts);
251251+ request = await applyRequestInterceptors(request, opts, networkBody);
239252 return request;
240253 },
241254 serializedBody: networkBody as BodyInit | null | undefined,
···125125 const applyRequestInterceptors = async (
126126 request: Request,
127127 opts: ResolvedRequestOptions,
128128+ body: BodyInit | null | undefined,
128129 ) => {
129130 for (const fn of interceptors.request.fns) {
130131 if (fn) {
···138139 // body comes only from getValidRequestBody(options)
139140 // reflect signal if present
140141 opts.signal = (request as any).signal as AbortSignal | undefined;
142142+143143+ // When body is FormData, remove Content-Type header to avoid boundary mismatch.
144144+ // Note: We already delete Content-Type in resolveOptions for FormData, but the
145145+ // Request constructor (line 175) re-adds it with an auto-generated boundary.
146146+ // Since we pass the original FormData (not the Request's body) to ofetch, and
147147+ // ofetch will generate its own boundary, we must remove the Request's Content-Type
148148+ // to let ofetch set the correct one. Otherwise the boundary in the header won't
149149+ // match the boundary in the actual multipart body sent by ofetch.
150150+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
151151+ opts.headers.delete('Content-Type');
152152+ }
153153+141154 return request;
142155 };
143156···176189 };
177190 let request = new Request(url, requestInit);
178191179179- request = await applyRequestInterceptors(request, opts);
192192+ request = await applyRequestInterceptors(request, opts, networkBody);
180193 const finalUrl = request.url;
181194182195 // build ofetch options and perform the request (.raw keeps the Response)
···235248 method,
236249 onRequest: async (url, init) => {
237250 let request = new Request(url, init);
238238- request = await applyRequestInterceptors(request, opts);
251251+ request = await applyRequestInterceptors(request, opts, networkBody);
239252 return request;
240253 },
241254 serializedBody: networkBody as BodyInit | null | undefined,
···125125 const applyRequestInterceptors = async (
126126 request: Request,
127127 opts: ResolvedRequestOptions,
128128+ body: BodyInit | null | undefined,
128129 ) => {
129130 for (const fn of interceptors.request.fns) {
130131 if (fn) {
···138139 // body comes only from getValidRequestBody(options)
139140 // reflect signal if present
140141 opts.signal = (request as any).signal as AbortSignal | undefined;
142142+143143+ // When body is FormData, remove Content-Type header to avoid boundary mismatch.
144144+ // Note: We already delete Content-Type in resolveOptions for FormData, but the
145145+ // Request constructor (line 175) re-adds it with an auto-generated boundary.
146146+ // Since we pass the original FormData (not the Request's body) to ofetch, and
147147+ // ofetch will generate its own boundary, we must remove the Request's Content-Type
148148+ // to let ofetch set the correct one. Otherwise the boundary in the header won't
149149+ // match the boundary in the actual multipart body sent by ofetch.
150150+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
151151+ opts.headers.delete('Content-Type');
152152+ }
153153+141154 return request;
142155 };
143156···176189 };
177190 let request = new Request(url, requestInit);
178191179179- request = await applyRequestInterceptors(request, opts);
192192+ request = await applyRequestInterceptors(request, opts, networkBody);
180193 const finalUrl = request.url;
181194182195 // build ofetch options and perform the request (.raw keeps the Response)
···235248 method,
236249 onRequest: async (url, init) => {
237250 let request = new Request(url, init);
238238- request = await applyRequestInterceptors(request, opts);
251251+ request = await applyRequestInterceptors(request, opts, networkBody);
239252 return request;
240253 },
241254 serializedBody: networkBody as BodyInit | null | undefined,