Fix auth header lost on multipart task completion requests
The createCompletionWithImages method used client.post() with a manual MultiPartFormDataContent body, which can override the Authorization header. Switch to submitFormWithBinaryData() (matching DocumentApi's working pattern) which properly separates form data from request headers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import com.example.casera.models.*
|
|||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import io.ktor.client.call.*
|
import io.ktor.client.call.*
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
|
import io.ktor.client.request.forms.*
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
|
|
||||||
class TaskCompletionApi(private val client: HttpClient = ApiClient.httpClient) {
|
class TaskCompletionApi(private val client: HttpClient = ApiClient.httpClient) {
|
||||||
@@ -100,34 +101,31 @@ class TaskCompletionApi(private val client: HttpClient = ApiClient.httpClient) {
|
|||||||
imageFileNames: List<String> = emptyList()
|
imageFileNames: List<String> = emptyList()
|
||||||
): ApiResult<WithSummaryResponse<TaskCompletionResponse>> {
|
): ApiResult<WithSummaryResponse<TaskCompletionResponse>> {
|
||||||
return try {
|
return try {
|
||||||
val response = client.post("$baseUrl/task-completions/") {
|
val response = client.submitFormWithBinaryData(
|
||||||
header("Authorization", "Token $token")
|
url = "$baseUrl/task-completions/",
|
||||||
|
formData = formData {
|
||||||
|
// Add text fields
|
||||||
|
append("task_id", request.taskId.toString())
|
||||||
|
request.completedAt?.let { append("completed_at", it) }
|
||||||
|
request.actualCost?.let { append("actual_cost", it.toString()) }
|
||||||
|
request.notes?.let { append("notes", it) }
|
||||||
|
request.rating?.let { append("rating", it.toString()) }
|
||||||
|
|
||||||
setBody(
|
// Add image files
|
||||||
io.ktor.client.request.forms.MultiPartFormDataContent(
|
images.forEachIndexed { index, imageBytes ->
|
||||||
io.ktor.client.request.forms.formData {
|
val fileName = imageFileNames.getOrNull(index) ?: "image_$index.jpg"
|
||||||
// Add text fields
|
append(
|
||||||
append("task_id", request.taskId.toString())
|
"images",
|
||||||
request.completedAt?.let { append("completed_at", it) }
|
imageBytes,
|
||||||
request.actualCost?.let { append("actual_cost", it.toString()) }
|
Headers.build {
|
||||||
request.notes?.let { append("notes", it) }
|
append(HttpHeaders.ContentType, "image/jpeg")
|
||||||
request.rating?.let { append("rating", it.toString()) }
|
append(HttpHeaders.ContentDisposition, "filename=\"$fileName\"")
|
||||||
|
|
||||||
// Add image files
|
|
||||||
images.forEachIndexed { index, imageBytes ->
|
|
||||||
val fileName = imageFileNames.getOrNull(index) ?: "image_$index.jpg"
|
|
||||||
append(
|
|
||||||
"images",
|
|
||||||
imageBytes,
|
|
||||||
io.ktor.http.Headers.build {
|
|
||||||
append(HttpHeaders.ContentType, "image/jpeg")
|
|
||||||
append(HttpHeaders.ContentDisposition, "filename=\"$fileName\"")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
)
|
}
|
||||||
)
|
}
|
||||||
|
) {
|
||||||
|
header("Authorization", "Token $token")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.status.isSuccess()) {
|
if (response.status.isSuccess()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user