mirror of
https://github.com/tenrok/axios.git
synced 2026-06-23 20:40:40 +03:00
fix(fetch): remove Content-Type without boundary for FormData (#7314)
* fix(fetch): remove Content-Type without boundary for FormData When using the fetch adapter with FormData and manually setting Content-Type to 'multipart/form-data' (without boundary), the request would fail because the boundary is required. This fix detects when Content-Type is set to multipart/form-data without a boundary and removes it, allowing fetch to automatically set the correct Content-Type header with the proper boundary. Fixes #7054 * chore: update fixes --------- Co-authored-by: Jason Saayman <jasonsaayman@gmail.com>
This commit is contained in:
@@ -221,6 +221,19 @@ const factory = (env) => {
|
|||||||
// see https://github.com/cloudflare/workerd/issues/902
|
// see https://github.com/cloudflare/workerd/issues/902
|
||||||
const isCredentialsSupported = isRequestSupported && 'credentials' in Request.prototype;
|
const isCredentialsSupported = isRequestSupported && 'credentials' in Request.prototype;
|
||||||
|
|
||||||
|
// If data is FormData and Content-Type is multipart/form-data without boundary,
|
||||||
|
// delete it so fetch can set it correctly with the boundary
|
||||||
|
if (utils.isFormData(data)) {
|
||||||
|
const contentType = headers.getContentType();
|
||||||
|
if (
|
||||||
|
contentType &&
|
||||||
|
/^multipart\/form-data/i.test(contentType) &&
|
||||||
|
!/boundary=/i.test(contentType)
|
||||||
|
) {
|
||||||
|
headers.delete('content-type');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const resolvedOptions = {
|
const resolvedOptions = {
|
||||||
...fetchOptions,
|
...fetchOptions,
|
||||||
signal: composedSignal,
|
signal: composedSignal,
|
||||||
|
|||||||
@@ -550,6 +550,54 @@ describe.runIf(typeof fetch === 'function')('supports fetch with nodejs', () =>
|
|||||||
await stopHTTPServer(server);
|
await stopHTTPServer(server);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should remove manually set Content-Type without boundary for FormData', async () => {
|
||||||
|
const form = new FormData();
|
||||||
|
form.append('foo', 'bar');
|
||||||
|
|
||||||
|
const server = await startHTTPServer(
|
||||||
|
(req, res) => {
|
||||||
|
const contentType = req.headers['content-type'];
|
||||||
|
assert.match(contentType, /^multipart\/form-data; boundary=/i);
|
||||||
|
res.end('OK');
|
||||||
|
},
|
||||||
|
{ port: SERVER_PORT }
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fetchAxios.post(`http://localhost:${server.address().port}/form`, form, {
|
||||||
|
headers: { 'Content-Type': 'multipart/form-data' },
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
await stopHTTPServer(server);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should preserve Content-Type if it already has boundary', async () => {
|
||||||
|
const form = new FormData();
|
||||||
|
form.append('foo', 'bar');
|
||||||
|
|
||||||
|
const customBoundary = '----CustomBoundary123';
|
||||||
|
|
||||||
|
const server = await startHTTPServer(
|
||||||
|
(req, res) => {
|
||||||
|
const contentType = req.headers['content-type'];
|
||||||
|
assert.ok(contentType.includes(customBoundary));
|
||||||
|
res.end('OK');
|
||||||
|
},
|
||||||
|
{ port: SERVER_PORT }
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fetchAxios.post(`http://localhost:${server.address().port}/form`, form, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': `multipart/form-data; boundary=${customBoundary}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
await stopHTTPServer(server);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('env config', () => {
|
describe('env config', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user