Default content-type of application/json applied to requests even when no body
frdwhite24 opened this issue · comments
Description
Thanks for all the hard work on this library, it's an incredible feat and has saved me so much time in my personal projects. I make sure to recommend it to everyone who has a similar problem. Also loving the type safety and flexibility of the latest lib version! I've not felt restricted when used it at all.
I've recently upgraded to the latest version of your lib (0.46.0), and have switched from using axios as the client to @hey-api/client-fetch (0.1.3) because I needed to add custom headers in an interceptor. Previously all requests worked fine, but after carrying out the appropriate refactoring for the new library version and config format, the requests without a body are failing with a FastifyError
from my backend of:
Body cannot be empty when
content-type
is set to 'application/json'
Inspecting the requests shows there is indeed a header with content-type: "application/json"
being applied. If I write the following code in a request interceptor, then the requests (namely POST and DELETE) go through just fine as before. It seems there is a default content-type
of application/json
being applied?
client.interceptors.request.use(async (request) => {
const token = await getToken()
request.headers.set('Authorization', `Bearer ${token}`)
if (some condition here) {
request.headers.delete('content-type')
return request
})
I'm not sure of the best way to handle this, but feel free to ask any more questions if you need to so we can figure it out together.
OpenAPI specification (optional)
{
"openapi":"3.0.3",
"info":{
"title":"MyApp",
"description":"REST API for MyApp",
"version":"1.0.0"
},
"components":{
},
"paths":{
"/api/flights/{flightId}":{
"delete":{
"operationId":"deleteOneFlight",
"tags":[
"Flight"
],
"parameters":[
{
"schema":{
"type":"string"
},
"in":"path",
"name":"flightId",
"required":true
}
],
"responses":{
"204":{
"description":"Default Response",
"content":{
"application/json":{
"schema":{
"type":"object",
"properties":{
}
}
}
}
}
}
}
}
}
}
Configuration
// openapi-ts.config.ts
import { defineConfig } from '@hey-api/openapi-ts'
export default defineConfig({
client: '@hey-api/client-fetch',
input: 'openapi.json',
output: {
format: 'prettier',
path: 'src/api/generated'
},
types: {
enums: 'javascript',
},
})
System information (optional)
- MacOS: Sonoma v14.5
- node: v20.12.2
- npm: v10.5.0
- @hey-api/client-fetch: v0.1.3 <- previously axios v1.6.8
- @hey-api/openapi-ts: v0.46.3 <- previously v0.43.0
- react-native: v0.73.6
- expo: v50.0.19
The same thing seems to happen with a POST request that doesn't have any body as well, have updated the original issue text/title and solution
For anyone else experiencing this, you can use the temporary workaround below. I think this is definitely something that should be addressed with the new @hey-api/client-fetch lib. I've had to go through all my endpoints and manually pick out the ones that: are not GET, and don't send a body, and remove their content-type
header.
client.interceptors.request.use(async (request) => {
const method = request.method
if (method === 'DELETE' || method === 'POST') { // or any other methods where you're sending something without a body (GET isn't required)
ENDPOINTS_TO_REMOVE[method].forEach((endpoint) => {
if (endpoint.regex.test(request.url)) {
request.headers.delete('content-type')
}
})
}
return request
})
where:
export const ENDPOINTS_TO_REMOVE = {
DELETE: [
{
url: '/api/my-endpoint',
regex: /\/api\/my-endpoint/, // using regex just in case you have url parameters
}
]
Probably, if you use @hey-api/client-fetch
there is simpler workaround:
client.interceptors.request.use((request, options) => {
// ...
if(!options.body) request.headers.delete('content-type')
return request
});
I faced this problem in .NET 8 backend. I send simple get
request, but if content-type
header specified, .NET Model binding system tries to get data from body and i get binding error. Even if i explicitly specify to bind model from query.
In my opinion content-type
header should be removed in all request methods of clients packages if options.body
is null
or undefined
(at least in get
method).