aboutsummaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authoradamw <adam@warski.org>2017-08-04 13:06:36 +0200
committeradamw <adam@warski.org>2017-08-04 13:06:36 +0200
commit69d7ee463848a620b80742a8c38c5798af909479 (patch)
tree53645133d1060960b9c5b5eaf0a4e2112258206c /core/src
parentab566fd5cf0f54e8e69b2917b32e57f2321d49ee (diff)
downloadsttp-69d7ee463848a620b80742a8c38c5798af909479.tar.gz
sttp-69d7ee463848a620b80742a8c38c5798af909479.tar.bz2
sttp-69d7ee463848a620b80742a8c38c5798af909479.zip
Extracting common logic for handling basic responses eagerly
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/MonadError.scala3
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/model/ResponseAs.scala46
2 files changed, 43 insertions, 6 deletions
diff --git a/core/src/main/scala/com/softwaremill/sttp/MonadError.scala b/core/src/main/scala/com/softwaremill/sttp/MonadError.scala
index e5e7ab8..40cea4b 100644
--- a/core/src/main/scala/com/softwaremill/sttp/MonadError.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/MonadError.scala
@@ -2,6 +2,7 @@ package com.softwaremill.sttp
import scala.concurrent.{ExecutionContext, Future, Promise}
import scala.language.higherKinds
+import scala.util.Try
trait MonadError[R[_]] {
def unit[T](t: T): R[T]
@@ -10,6 +11,8 @@ trait MonadError[R[_]] {
def error[T](t: Throwable): R[T]
def flatten[T](ffa: R[R[T]]): R[T] = flatMap[R[T], T](ffa, identity)
+
+ def fromTry[T](t: Try[T]): R[T] = t.fold(error, unit)
}
trait MonadAsyncError[R[_]] extends MonadError[R] {
diff --git a/core/src/main/scala/com/softwaremill/sttp/model/ResponseAs.scala b/core/src/main/scala/com/softwaremill/sttp/model/ResponseAs.scala
index cf9bc12..3862483 100644
--- a/core/src/main/scala/com/softwaremill/sttp/model/ResponseAs.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/model/ResponseAs.scala
@@ -2,24 +2,37 @@ package com.softwaremill.sttp.model
import java.net.URLDecoder
+import com.softwaremill.sttp.MonadError
+
import scala.collection.immutable.Seq
+import scala.language.higherKinds
+import scala.util.Try
/**
* @tparam T Target type as which the response will be read.
* @tparam S If `T` is a stream, the type of the stream. Otherwise, `Nothing`.
*/
sealed trait ResponseAs[T, +S] {
- def map[T2](f: T => T2): ResponseAs[T2, S] =
+ def map[T2](f: T => T2): ResponseAs[T2, S]
+}
+
+/**
+ * Response handling specification which isn't derived from another response
+ * handling method, but needs to be handled directly by the backend.
+ */
+sealed trait BasicResponseAs[T, +S] extends ResponseAs[T, S] {
+ override def map[T2](f: (T) => T2): ResponseAs[T2, S] =
MappedResponseAs[T, T2, S](this, f)
}
-case object IgnoreResponse extends ResponseAs[Unit, Nothing]
+case object IgnoreResponse extends BasicResponseAs[Unit, Nothing]
case class ResponseAsString(encoding: String)
- extends ResponseAs[String, Nothing]
-case object ResponseAsByteArray extends ResponseAs[Array[Byte], Nothing]
+ extends BasicResponseAs[String, Nothing]
+case object ResponseAsByteArray extends BasicResponseAs[Array[Byte], Nothing]
case class ResponseAsStream[T, S]()(implicit val responseIsStream: S =:= T)
- extends ResponseAs[T, S]
-case class MappedResponseAs[T, T2, S](raw: ResponseAs[T, S], g: T => T2)
+ extends BasicResponseAs[T, S]
+
+case class MappedResponseAs[T, T2, S](raw: BasicResponseAs[T, S], g: T => T2)
extends ResponseAs[T2, S] {
override def map[T3](f: T2 => T3): ResponseAs[T3, S] =
MappedResponseAs[T, T3, S](raw, g andThen f)
@@ -38,4 +51,25 @@ object ResponseAs {
case _ => None
})
}
+
+ /**
+ * Handles responses according to the given specification when basic
+ * response specifications can be handled eagerly, that is without
+ * wrapping the result in the target monad (`handleBasic` returns
+ * `Try[T]`, not `R[T]`).
+ */
+ private[sttp] trait EagerResponseHandler[S] {
+ def handleBasic[T](bra: BasicResponseAs[T, S]): Try[T]
+
+ def handle[T, R[_]](responseAs: ResponseAs[T, S],
+ responseMonad: MonadError[R]): R[T] = {
+
+ responseAs match {
+ case mra @ MappedResponseAs(raw, g) =>
+ responseMonad.map(responseMonad.fromTry(handleBasic(mra.raw)), mra.g)
+ case bra: BasicResponseAs[T, S] =>
+ responseMonad.fromTry(handleBasic(bra))
+ }
+ }
+ }
}