diff --git a/build.sbt b/build.sbt index d56b6178d5..cee034d5f4 100644 --- a/build.sbt +++ b/build.sbt @@ -146,7 +146,7 @@ val scalaTest = libraryDependencies ++= Seq("freespec", "funsuite", "flatspec", val zioVersion = "1.0.3" val zioInteropRsVersion = "1.3.0.7-2" -val sttpModelVersion = "1.2.0-RC5" +val sttpModelVersion = "1.2.0-RC6" val sttpSharedVersion = "1.0.0-RC8" val logback = "ch.qos.logback" % "logback-classic" % "1.2.3" diff --git a/core/src/test/scala/sttp/client3/testing/HttpTest.scala b/core/src/test/scala/sttp/client3/testing/HttpTest.scala index f723c8d902..416d18ffa4 100644 --- a/core/src/test/scala/sttp/client3/testing/HttpTest.scala +++ b/core/src/test/scala/sttp/client3/testing/HttpTest.scala @@ -383,6 +383,18 @@ trait HttpTest[F[_]] req.send(backend).toFuture().map { resp => resp.body should be("p1=v1 (f1), p2=v2 (f2)") } } + "send a multipart message with binary data and filename" in { + val binaryPart = { + multipart("p1", "v1".getBytes) + .fileName("f1") + } + val req = mp.multipartBody(binaryPart) + req.send(backend).toFuture().map { resp => + resp.body should include("f1") + resp.body should include("v1") + } + } + if (supportsCustomMultipartContentType) { "send a multipart message with custom content type" in { val req = basicRequest diff --git a/httpclient-backend/src/main/scala/sttp/client3/httpclient/BodyToHttpClient.scala b/httpclient-backend/src/main/scala/sttp/client3/httpclient/BodyToHttpClient.scala index d50f9fd11f..e32ea346a0 100644 --- a/httpclient-backend/src/main/scala/sttp/client3/httpclient/BodyToHttpClient.scala +++ b/httpclient-backend/src/main/scala/sttp/client3/httpclient/BodyToHttpClient.scala @@ -59,21 +59,20 @@ private[httpclient] trait BodyToHttpClient[F[_], S] { private def multipartBody[T](parts: Seq[Part[RequestBody[_]]]) = { val multipartBuilder = new MultiPartBodyPublisher() parts.foreach { p => - val allHeaders = p.headers :+ Header(HeaderNames.ContentDisposition, p.contentDispositionHeaderValue) + val allHeaders = Header(HeaderNames.ContentDisposition, p.contentDispositionHeaderValue) +: p.headers val partHeaders = allHeaders.map(h => h.name -> h.value).toMap.asJava - def fileName = p.fileName.getOrElse("") - def contentType = p.contentType.getOrElse(MediaType.ApplicationOctetStream.toString()) p.body match { case NoBody => // ignore case FileBody(f, _) => multipartBuilder.addPart(p.name, f.toFile.toPath, partHeaders) case StringBody(b, _, _) => multipartBuilder.addPart(p.name, b, partHeaders) case ByteArrayBody(b, _) => - multipartBuilder.addPart(p.name, supplier(new ByteArrayInputStream(b)), fileName, contentType) + multipartBuilder.addPart(p.name, supplier(new ByteArrayInputStream(b)), partHeaders) case ByteBufferBody(b, _) => if ((b: Buffer).isReadOnly()) - multipartBuilder.addPart(p.name, supplier(new ByteBufferBackedInputStream(b)), fileName, contentType) - else multipartBuilder.addPart(p.name, supplier(new ByteArrayInputStream(b.array())), fileName, contentType) - case InputStreamBody(b, _) => multipartBuilder.addPart(p.name, supplier(b), fileName, contentType) + multipartBuilder.addPart(p.name, supplier(new ByteBufferBackedInputStream(b)), partHeaders) + else + multipartBuilder.addPart(p.name, supplier(new ByteArrayInputStream(b.array())), partHeaders) + case InputStreamBody(b, _) => multipartBuilder.addPart(p.name, supplier(b), partHeaders) case StreamBody(_) => throw new IllegalArgumentException("Streaming multipart bodies are not supported") case MultipartBody(_) => throwNestedMultipartNotAllowed } @@ -81,9 +80,9 @@ private[httpclient] trait BodyToHttpClient[F[_], S] { multipartBuilder } - private def supplier[T](t: => T) = - new Supplier[T] { - override def get(): T = t + private def supplier(t: => InputStream) = + new Supplier[InputStream] { + override def get(): InputStream = t } // https://stackoverflow.com/a/6603018/362531 diff --git a/httpclient-backend/src/main/scala/sttp/client3/httpclient/MultiPartBodyPublisher.java b/httpclient-backend/src/main/scala/sttp/client3/httpclient/MultiPartBodyPublisher.java index 7775150732..47cba27c46 100644 --- a/httpclient-backend/src/main/scala/sttp/client3/httpclient/MultiPartBodyPublisher.java +++ b/httpclient-backend/src/main/scala/sttp/client3/httpclient/MultiPartBodyPublisher.java @@ -48,13 +48,12 @@ public MultiPartBodyPublisher addPart(String name, Path value, Map value, String filename, String contentType) { + public MultiPartBodyPublisher addPart(String name, Supplier value, Map headers) { PartsSpecification newPart = new PartsSpecification(); newPart.type = PartsSpecification.TYPE.STREAM; newPart.name = name; newPart.stream = value; - newPart.filename = filename; - newPart.contentType = contentType; + newPart.headers = headers; partsSpecificationList.add(newPart); return this; } @@ -77,8 +76,6 @@ public enum TYPE { String value; Path path; Supplier stream; - String filename; - String contentType; Map headers = new HashMap<>(); }