Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpClientBackend: fixed binary subparts' headers of a multipart request #776

Merged
merged 2 commits into from
Nov 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 12 additions & 0 deletions core/src/test/scala/sttp/client3/testing/HttpTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,31 +59,30 @@ 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
}
}
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,12 @@ public MultiPartBodyPublisher addPart(String name, Path value, Map<String, Strin
return this;
}

public MultiPartBodyPublisher addPart(String name, Supplier<InputStream> value, String filename, String contentType) {
public MultiPartBodyPublisher addPart(String name, Supplier<InputStream> value, Map<String, String> 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;
}
Expand All @@ -77,8 +76,6 @@ public enum TYPE {
String value;
Path path;
Supplier<InputStream> stream;
String filename;
String contentType;
Map<String, String> headers = new HashMap<>();
}

Expand Down