openapi-typescript
openapi-typescript copied to clipboard
Content-Type of type multipart must include a boundary parameter
Description
Hello, First, thanks a lot for this great library, it's very useful in one of the projects I am working on. I spent some to find the reason of the bug below so I thought to put it here for reference. Feel free to close the issue. => PR #1826 was a breaking change on our side as we migrated from 0.8.x to 0.12.x
POST requests with FormData were failing with Content-Type of type multipart must include a boundary parameter.
Reason is:
We had some code that was setting headers.set('Content-Type', 'multipart/form-data') (no idea why 🤔).
This header was removed in openapi-fetch prior to the PR. So the browser was setting the correct Content-Type.
After this PR, the header is now left in headers and therefore the browser does not set the correct Content-Type. Hence the issue. We fixed it by removing the line above.
Best! And again feel free to close this issue.
Hello, How are you doing 😊?
I ran into the same issue where setting 'Content-Type': 'multipart/form-data' in request headers caused the FormData payload to be sent as an empty object { }. Initially, I set the request header like this in both the middleware and the service:
const { data, error } = await client.POST('/api/media/upload', {
body: file as any,
headers: {
'content-type': 'multipart/form-data',
},
});
But the payload was empty. When I tried using native fetch in Next.js, everything worked fine, and the FormData was correctly sent with the full payload. I thought maybe I shouldn’t set the Content-Type manually, so I modified the service like this:
export const createMediaServices = (client: Client) => ({
upload: async (file: File) => {
try {
const { data, error } = await client.POST('/api/media/upload', {
body: file as any,
bodySerializer: (body) => {
const formData = new FormData();
formData.set('file', body!.file!);
console.log(formData.get('file'));
return formData;
},
});
return error ? R.Error(mapError(error)) : R.Ok(mappers.upload(data));
} catch {
return R.Error(mapError(undefined));
}
},
});
In the middleware, I’ve tried this approach:
export const requestMiddleware: Middleware['onRequest'] = async ({
request,
schemaPath,
}) => {
const isMedia = schemaPath === '/api/media/upload';
if (isMedia) {
return undefined;
}
const contentType = request.method.toUpperCase() === 'PATCH'
? 'application/merge-patch+json'
: 'application/ld+json';
request.headers.set('content-type', contentType);
return request;
};
However, it seems like openapi-fetch overrides the Content-Type and defaults to application/json, preventing the FormData from being processed correctly.
BTW I'm using version 0.10 of openapi-fetch
@gpichot
TY very much for reporting this.
However, I'd propose to close this as wontfix:
- It is expected to have breaking changes from 0.8.x to 0.12.x
- IMHO the new behavior implemented (in #1826) is a better API: if the caller explicitly requests a header, openapi-fetch will not override it anymore. Looking at the commit that introduced the mutable removal (https://github.com/salsita/openapi-typescript/commit/fd44bd28d881715e30f5a71435f05f6bae13859d#diff-97a780daf3f8f3dadada08409ebf769d5c22a115fb999160ce651ae0e93fb916), I'm pretty sure the intention was not to override explicit user provided headers, but just an oversight.