Server accepts all parameters except boolean one with Multipart form request data
So I have such request:
@Multipart
@POST("auth/...")
suspend fun sendExampleRequest(
@Part("enabled") enabled: Boolean,
@Part("name") name: String,
@Part photo: MultipartBody.Part
)
Call it from:
override suspend fun sendExampleRequest(
enabled: Boolean,
name: String,
photo : Uri
) {
try {
withContext(ioDispatcher) {
authApi.sendExampleRequest(
enabled = enabled,
name = name,
photo = document.toMultipartBodyPart(context, "photo")
)
}
} catch (e: Throwable) {
// ...
}
}
But server responds with error only for boolean parameter that it has the wrong value.
REQUEST:
--> POST https://...
Content-Type: multipart/form-data; boundary=240f3a38-2e91-4b6c-acd0-c04ba8c0e81a
Content-Length: 68700
accept: application/json
Authorization: Bearer ...
--240f3a38-2e91-4b6c-acd0-c04ba8c0e81a
Content-Disposition: form-data; name="enabled"
Content-Transfer-Encoding: binary
Content-Type: text/plain; charset=UTF-8
Content-Length: 4
true
--240f3a38-2e91-4b6c-acd0-c04ba8c0e81a
Content-Disposition: form-data; name="name"
Content-Transfer-Encoding: binary
Content-Type: text/plain; charset=UTF-8
Content-Length: 4
test
--240f3a38-2e91-4b6c-acd0-c04ba8c0e81a
Content-Disposition: form-data; name="document"; filename="test_photo_file.jpg"
Content-Type: image/jpeg
Content-Length: 67794
...
RESPONSE:
<-- 422 https://... (328ms)
server: nginx
date: Thu, 30 Mar 2023 16:49:08 GMT
content-type: application/json
cache-control: no-cache, private
x-ratelimit-limit: 60
x-ratelimit-remaining: 58
access-control-allow-origin: *
{"message":"The enabled field must be true or false.","errors":{"enabled":["The enabled field must be true or false."]}}
<-- END HTTP (149-byte body)
I can just send JSON body instead but without file:
{
"enabled": false,
"name": "test"
}
then it doesn't give error for boolean parameter but of course it gives the error about document file, so I can use only Multipart form to send all needed parameters but there is some issue with boolean parameters
Retrofit setup:
@Provides
@Singleton
fun provideRetrofit(
gson: Gson,
client: OkHttpClient,
queryConverterFactory: Converter.Factory
): Retrofit = Retrofit.Builder()
.baseUrl(BuildConfig.BASE_URL)
.client(client)
.addConverterFactory(queryConverterFactory)
.addConverterFactory(ScalarsConverterFactory.create()) // added it but didn't help
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
Solved. It's a PHP server issue:
it accepts 1
/0
only for form-data, a backend dev has to parse true
/false
as well