softwaremill / tapir

Rapid development of self-documenting APIs
https://tapir.softwaremill.com
Apache License 2.0
1.36k stars 418 forks source link

[BUG] multipartBody fails with ClassCastException when accessing part body #875

Closed pewniak747 closed 3 years ago

pewniak747 commented 3 years ago

Tapir version: 0.17.0-M10, 0.16.16

Scala version: 2.13.3

Describe the bug

An endpoint with a raw multipart body input (.in(multipartBody)) provides a faulty parts list to the server logic. Accessing the part's body throws an exception:

endpoint
 .post
 .in("api" / "echo" / "multipart")
 .in(multipartBody)
 .out(stringBody)
 .serverLogic { case (parts) => parts.map(part => s"${part.name}:${new String(part.body)}").mkString("\n").asRight[Unit] }
java.lang.ClassCastException: class scala.collection.immutable.$colon$colon cannot be cast to class [B (scala.collection.immutable.$colon$colon is in unnamed module of loader sbt.internal.ScalaLibraryClassLoader @6a40987d; [B is in module java.base of loader 'bootstrap')

How to reproduce?

I have implemented a test that reproduces this issue here:

https://github.com/softwaremill/tapir/compare/bugfix/multipart-body?expand=1

Additional information

I believe this is caused by incorrect typing of MultipartCodec.Default codec' higher-level value. The parts are typed as Seq[Part[Array[Byte]]] but the value in runtime is Seq[Part[Seq[Array[Byte]]]], because the codec is implemented with Codec.list(Codec.byteArray). Perhaps just adjusting the type of the codec would fix this.

https://github.com/softwaremill/tapir/blob/master/core/src/main/scala/sttp/tapir/Codec.scala#L503-L506

adamw commented 3 years ago

Released in 0.17.0