diff options
author | adamw <adam@warski.org> | 2017-08-03 11:38:23 +0200 |
---|---|---|
committer | adamw <adam@warski.org> | 2017-08-03 11:38:23 +0200 |
commit | c07f98349ac5dc646855d00425a9dc2c3324465e (patch) | |
tree | 6f07784a68290b406a3b50a59fac36b83c5df355 /core/src/main/scala | |
parent | 90615deb20ce43f09371b10a25628be8d68485d8 (diff) | |
download | sttp-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')
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] } |