aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/scala
diff options
context:
space:
mode:
authoradamw <adam@warski.org>2017-08-03 11:38:23 +0200
committeradamw <adam@warski.org>2017-08-03 11:38:23 +0200
commitc07f98349ac5dc646855d00425a9dc2c3324465e (patch)
tree6f07784a68290b406a3b50a59fac36b83c5df355 /core/src/main/scala
parent90615deb20ce43f09371b10a25628be8d68485d8 (diff)
downloadsttp-c07f98349ac5dc646855d00425a9dc2c3324465e.tar.gz
sttp-c07f98349ac5dc646855d00425a9dc2c3324465e.tar.bz2
sttp-c07f98349ac5dc646855d00425a9dc2c3324465e.zip
Making the response monad a top-level concept, to make it possible to write SttpHandler wrappers.
Diffstat (limited to 'core/src/main/scala')
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionSttpHandler.scala2
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/MonadError.scala44
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala5
3 files changed, 51 insertions, 0 deletions
diff --git a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionSttpHandler.scala b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionSttpHandler.scala
index 6c3368a..d5c2ccd 100644
--- a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionSttpHandler.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionSttpHandler.scala
@@ -33,6 +33,8 @@ object HttpURLConnectionSttpHandler extends SttpHandler[Id, Nothing] {
}
}
+ override def responseMonad: MonadError[Id] = IdMonad
+
private def setBody(body: RequestBody[Nothing], c: HttpURLConnection): Unit = {
if (body != NoBody) c.setDoOutput(true)
diff --git a/core/src/main/scala/com/softwaremill/sttp/MonadError.scala b/core/src/main/scala/com/softwaremill/sttp/MonadError.scala
new file mode 100644
index 0000000..e5e7ab8
--- /dev/null
+++ b/core/src/main/scala/com/softwaremill/sttp/MonadError.scala
@@ -0,0 +1,44 @@
+package com.softwaremill.sttp
+
+import scala.concurrent.{ExecutionContext, Future, Promise}
+import scala.language.higherKinds
+
+trait MonadError[R[_]] {
+ def unit[T](t: T): R[T]
+ def map[T, T2](fa: R[T], f: T => T2): R[T2]
+ def flatMap[T, T2](fa: R[T], f: T => R[T2]): R[T2]
+ def error[T](t: Throwable): R[T]
+
+ def flatten[T](ffa: R[R[T]]): R[T] = flatMap[R[T], T](ffa, identity)
+}
+
+trait MonadAsyncError[R[_]] extends MonadError[R] {
+ def async[T](register: (Either[Throwable, T] => Unit) => Unit): R[T]
+}
+
+object IdMonad extends MonadError[Id] {
+ override def unit[T](t: T): Id[T] = t
+ override def map[T, T2](fa: Id[T], f: (T) => T2): Id[T2] = f(fa)
+ override def flatMap[T, T2](fa: Id[T], f: (T) => Id[T2]): Id[T2] = f(fa)
+ override def error[T](t: Throwable): Id[T] = throw t
+}
+
+class FutureMonad(implicit ec: ExecutionContext)
+ extends MonadAsyncError[Future] {
+
+ override def unit[T](t: T): Future[T] = Future.successful(t)
+ override def map[T, T2](fa: Future[T], f: (T) => T2): Future[T2] = fa.map(f)
+ override def flatMap[T, T2](fa: Future[T], f: (T) => Future[T2]): Future[T2] =
+ fa.flatMap(f)
+ override def error[T](t: Throwable): Future[T] = Future.failed(t)
+
+ override def async[T](
+ register: ((Either[Throwable, T]) => Unit) => Unit): Future[T] = {
+ val p = Promise[T]()
+ register {
+ case Left(t) => p.failure(t)
+ case Right(t) => p.success(t)
+ }
+ p.future
+ }
+}
diff --git a/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala b/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala
index 800d66a..bdcc1b5 100644
--- a/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala
@@ -11,4 +11,9 @@ import scala.language.higherKinds
trait SttpHandler[R[_], -S] {
def send[T](request: Request[T, S]): R[Response[T]]
def close(): Unit = {}
+ /**
+ * The monad in which the responses are wrapped. Allows writing wrapper
+ * handlers, which map/flatMap over the return value of [[send]].
+ */
+ def responseMonad: MonadError[R]
}