Improve multipart features for httpPost and httpUpload
See original GitHub issueFeature Request
With the current API, some scenarios of multipart interaction are not friendly and require what imho are hacks.
Description
I am working with CMS API and there’s a API call with requires uploading a document alongside metadata in JSON. This is easily done in curl with:
curl "https://api.hostname/v1/documents" \
-X POST \
-H 'Content-Type: multipart/form-data' \
-H "Authorization: Bearer $token" \
-H "Repository-Id: $repo_id" \
-F metadata="{
\"description\": \"Test document\",
\"categories\": [{...}]
};type=application/json" \
-F file=@file_path
I only got this to work with the following code
val (request, response, result) = url.httpUpload(
// parameters = listOf("metadata" to """{"description":"test document from Kotlin"};type=application/json""")
)
.dataParts { request, url ->
listOf(
DataPart(File("src/main/resources/rust-logo-blk.svg"), "file"),
DataPart(File("src/main/resources/doc.json"), "metadata","application/json")
)
}
.header("Authorization" to "Bearer $token")
.header("Repository-Id" to repoId)
.responseString()
As you can see this requires storing the JSON in a file. That’s because I could not find any way to set the Content-Type for the part other than using DataPart
. Using parameters
as seen in the commented line sets it as text/plain
causing the service to return an error.
I also tried something like
val (request, response, result) = url.httpPost(listOf(
"metadata" to """{"description":"test document from Kotlin"}""",
"file" to DataPart(File("resources/rust-logo-blk.svg"))))
.header("Content-Type" to "multipart/form-data")
.header("Authorization" to "Bearer $token")
.header("Repo-Id" to repoId)
.responseString()
Proposed Solution
Imho, the naming upload
is confusing for this cases but is very useful for simple 1 file uploads. I’d advocate to:
- Create a httpMultipart similar to httpPost that offers the ability to pass any kind of object, not only files and set the Content-Type. Or allow htttPost to set Content-Type to multipart so that it manages the format internally (a la curl).
- Extend DataPart to support any data (String, Inputstream, …)
Probably, with only point 2 would be enough to support a cleaner method with httpUpload.
Alternatives I’ve considered
Current solution does not allow to generate metadata Json on-the fly, which is not valid for a dynamic system.
Also, the dataParts
closure element seems cumbersome to me and does not help readability. I prefer simpler/cleaner httpPost
syntax. But this is a more personal thing.
Additional context
I noticed that when no Content-Type is set in the DataPart, the header is added empty, maybe this could be just removed.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:2
- Comments:8
Top GitHub Comments
Can’t promise, but I’ll have a look at it asap this week.
Cool! Thanks a lot, do not hesitate to mention me if you need a beta tester.