Skip to content

Commit

Permalink
Merge pull request #56 from joshlemer/try-monad-error
Browse files Browse the repository at this point in the history
Add TryMonad, implement a delegating TryBackend
  • Loading branch information
adamw committed Dec 27, 2017
2 parents 9174caf + 763a9f0 commit 21e8fab
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 0 deletions.
9 changes: 9 additions & 0 deletions core/src/main/scala/com/softwaremill/sttp/MonadError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,16 @@ object IdMonad extends MonadError[Id] {
override protected def handleWrappedError[T](rt: Id[T])(
h: PartialFunction[Throwable, Id[T]]): Id[T] = rt
}
object TryMonad extends MonadError[Try] {
override def unit[T](t: T): Try[T] = Success(t)
override def map[T, T2](fa: Try[T])(f: (T) => T2): Try[T2] = fa.map(f)
override def flatMap[T, T2](fa: Try[T])(f: (T) => Try[T2]): Try[T2] =
fa.flatMap(f)

override def error[T](t: Throwable): Try[T] = Failure(t)
override protected def handleWrappedError[T](rt: Try[T])(
h: PartialFunction[Throwable, Try[T]]): Try[T] = rt.recoverWith(h)
}
class FutureMonad(implicit ec: ExecutionContext)
extends MonadAsyncError[Future] {

Expand Down
28 changes: 28 additions & 0 deletions core/src/main/scala/com/softwaremill/sttp/TryBackend.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.softwaremill.sttp

import java.net.HttpURLConnection

import scala.util.Try

/** A Backend that safely wraps SttpBackend exceptions in Try's
*
* @param delegate An SttpBackend which to which this backend forwards all requests
* @tparam S The type of streams that are supported by the backend. `Nothing`,
* if streaming requests/responses is not supported by this backend.
*/
class TryBackend[-S](delegate: SttpBackend[Id, S]) extends SttpBackend[Try, S] {
override def send[T](request: Request[T, S]): Try[Response[T]] =
Try(delegate.send(request))

override def close(): Unit = delegate.close()

override def responseMonad: MonadError[Try] = TryMonad
}

object TryHttpUrlConnectionBackend {
def apply(options: SttpBackendOptions = SttpBackendOptions.Default,
customizeConnection: HttpURLConnection => Unit = _ => ())
: SttpBackend[Try, Nothing] =
new TryBackend[Nothing](
HttpURLConnectionBackend(options, customizeConnection))
}
1 change: 1 addition & 0 deletions docs/backends/summary.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Below is a summary of all the backends. See the sections on individual backend i
Class Response wrapper Supported stream type
================================ ============================ ================================================
``HttpURLConnectionBackend`` None (``Id``) n/a
``TryHttpURLConnectionBackend`` ``scala.util.Try`` n/a
``AkkaHttpBackend`` ``scala.concurrent.Future`` ``akka.stream.scaladsl.Source[ByteString, Any]``
``AsyncHttpClientFutureBackend`` ``scala.concurrent.Future`` n/a
``AsyncHttpClientScalazBackend`` ``scalaz.concurrent.Task`` n/a
Expand Down
4 changes: 4 additions & 0 deletions tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ class BasicTests

runTests("HttpURLConnection")(HttpURLConnectionBackend(),
ForceWrappedValue.id)

runTests("TryHttpURLConnection")(TryHttpUrlConnectionBackend(),
ForceWrappedValue.scalaTry)

runTests("Akka HTTP")(AkkaHttpBackend.usingActorSystem(actorSystem),
ForceWrappedValue.future)
runTests("Async Http Client - Future")(AsyncHttpClientFutureBackend(),
Expand Down
6 changes: 6 additions & 0 deletions tests/src/test/scala/com/softwaremill/sttp/testHelpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import org.scalatest.{BeforeAndAfterAll, Suite}
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.language.higherKinds
import scala.util.Try
import scalaz._

trait TestHttpServer
Expand Down Expand Up @@ -50,6 +51,11 @@ object ForceWrappedValue extends ScalaFutures with TestingPatience {
override def force[T](wrapped: Id[T]): T =
wrapped
}

val scalaTry = new ForceWrappedValue[Try] {
override def force[T](wrapped: Try[T]): T = wrapped.get
}

val future = new ForceWrappedValue[Future] {

override def force[T](wrapped: Future[T]): T =
Expand Down

0 comments on commit 21e8fab

Please sign in to comment.