diff --git a/zio-http/src/main/scala/zio/http/QueryParams.scala b/zio-http/src/main/scala/zio/http/QueryParams.scala index 7913a40053..9bc4793b3e 100644 --- a/zio-http/src/main/scala/zio/http/QueryParams.scala +++ b/zio-http/src/main/scala/zio/http/QueryParams.scala @@ -18,7 +18,7 @@ package zio.http import java.nio.charset.Charset -import zio.{Chunk, IO, ZIO} +import zio.{Chunk, IO, NonEmptyChunk, ZIO} import zio.http.codec.TextCodec import zio.http.internal.QueryParamEncoding @@ -91,17 +91,14 @@ final case class QueryParams(map: Map[String, Chunk[String]]) { /** * Retrieves all typed query parameter values having the specified name. */ - def getAllAs[A](key: String)(implicit codec: TextCodec[A]): Either[QueryParamsError, Chunk[A]] = - map.get(key) match { - case Some(params) => - params - .map(param => codec.decode(param).toRight(QueryParamsError.Malformed(key, param, codec))) - .partitionMap(identity) match { - case (errors, _) if errors.nonEmpty => Left(QueryParamsError.MultiMalformed(errors)) - case (_, typedParams) => Right(typedParams) - } - case None => Left(QueryParamsError.Missing(key)) - } + def getAllAs[A](key: String)(implicit codec: TextCodec[A]): Either[QueryParamsError, Chunk[A]] = for { + params <- map.get(key).toRight(QueryParamsError.Missing(key)) + (failed, typed) = params.map(p => codec.decode(p).toRight(p)).partitionMap(identity) + result <- NonEmptyChunk + .fromChunk(failed) + .map(fails => QueryParamsError.Malformed(key, codec, fails)) + .toLeft(typed) + } yield result /** * Retrieves all typed query parameter values having the specified name as @@ -120,7 +117,7 @@ final case class QueryParams(map: Map[String, Chunk[String]]) { */ def getAs[A](key: String)(implicit codec: TextCodec[A]): Either[QueryParamsError, A] = for { param <- get(key).toRight(QueryParamsError.Missing(key)) - typedParam <- codec.decode(param).toRight(QueryParamsError.Malformed(key, param, codec)) + typedParam <- codec.decode(param).toRight(QueryParamsError.Malformed(key, codec, NonEmptyChunk(param))) } yield typedParam /** diff --git a/zio-http/src/main/scala/zio/http/QueryParamsError.scala b/zio-http/src/main/scala/zio/http/QueryParamsError.scala index 4ff65ab9a7..c74e02bdce 100644 --- a/zio-http/src/main/scala/zio/http/QueryParamsError.scala +++ b/zio-http/src/main/scala/zio/http/QueryParamsError.scala @@ -20,7 +20,7 @@ import java.nio.charset.Charset import scala.util.control.NoStackTrace -import zio.Chunk +import zio.{Chunk, NonEmptyChunk} import zio.http.codec.TextCodec import zio.http.internal.QueryParamEncoding @@ -30,15 +30,13 @@ sealed trait QueryParamsError extends Exception with NoStackTrace { def message: String } object QueryParamsError { - final case class Missing(queryParamName: String) extends QueryParamsError { - def message = s"Missing query parameter with name $queryParamName" + final case class Missing(name: String) extends QueryParamsError { + def message = s"Missing query parameter with name $name" } - final case class Malformed(name: String, value: String, codec: TextCodec[_]) extends QueryParamsError { - def message = s"Unable to decode query parameter with name $name and value $value using $codec" - } - - final case class MultiMalformed(chunk: Chunk[Malformed]) extends QueryParamsError { - def message: String = chunk.map(_.getMessage()).mkString("; ") + final case class Malformed(name: String, codec: TextCodec[_], values: NonEmptyChunk[String]) + extends QueryParamsError { + def message: String = + s"Unable to decode query parameter $name with values [ ${values.mkString(", ")} ] using ${codec.describe} codec" } }