request.toCurl is great for sharing a request to debug, but for multipart bodies it silently throws away Part.fileName, Part.contentType, and Part.headers. The resulting curl command sends a different request than the original.
Reproducer (scala-cli):
//> using scala 3.8.3
//> using dep com.softwaremill.sttp.client4::core::4.0.5
import sttp.client4.*
import sttp.model.*
@main def run(): Unit =
val request = basicRequest
.post(uri"http://example.com/upload")
.multipartBody(
multipart("file", "file content")
.fileName("document.pdf")
.contentType("application/pdf"),
multipart("field", "value")
)
println(request.toCurl)
Output:
curl \
--request POST \
--url 'http://example.com/upload' \
--form 'file=file content' \
--form 'field=value' \
--location \
--max-redirs 32
Expected something like --form 'file=file content;filename=document.pdf;type=application/pdf'.
Source:
|
def handleMultipartBody(parts: Seq[Part[GenericRequestBody[_]]]): String = |
|
parts |
|
.map { p => |
|
p.body match { |
|
case StringBody(s, _, _) => s"--form '${p.name}=$s'" |
|
case FileBody(f, _) => s"--form '${p.name}=@${f.name}'" |
|
case _ => s"--data-binary <PLACEHOLDER>" |
|
} |
|
} |
|
.mkString(newline) |
def handleMultipartBody(parts: Seq[Part[GenericRequestBody[_]]]): String =
parts.map { p =>
p.body match {
case StringBody(s, _, _) => s"--form '${p.name}=$s'"
case FileBody(f, _) => s"--form '${p.name}=@${f.name}'"
case _ => s"--data-binary <PLACEHOLDER>"
}
}.mkString(newline)
p.fileName, p.contentType, and p.headers aren't read at all, and any non-StringBody/FileBody part collapses to a literal placeholder. curl supports the metadata via the ;filename=...;type=... and ;headers=@... extensions, so a faithful renderer is feasible.
A sketch (StringBody case):
case StringBody(s, _, _) =>
val tail = (p.fileName.map(fn => s";filename=$fn").toList ++
p.contentType.map(ct => s";type=$ct").toList).mkString
s"--form '${p.name}=$s$tail'"
Happy to PR with full coverage of the four part-body shapes plus a unit test.
request.toCurlis great for sharing a request to debug, but for multipart bodies it silently throws awayPart.fileName,Part.contentType, andPart.headers. The resulting curl command sends a different request than the original.Reproducer (scala-cli):
Output:
Expected something like
--form 'file=file content;filename=document.pdf;type=application/pdf'.Source:
sttp/core/src/main/scala/sttp/client4/internal/ToCurlConverter.scala
Lines 58 to 67 in 6b817f7
p.fileName,p.contentType, andp.headersaren't read at all, and any non-StringBody/FileBodypart collapses to a literal placeholder. curl supports the metadata via the;filename=...;type=...and;headers=@...extensions, so a faithful renderer is feasible.A sketch (StringBody case):
Happy to PR with full coverage of the four part-body shapes plus a unit test.