diff options
author | adamw <adam@warski.org> | 2017-09-04 16:27:43 +0200 |
---|---|---|
committer | adamw <adam@warski.org> | 2017-09-04 16:27:43 +0200 |
commit | 2761923dcf1ea49f7671cc2f18df9bd07f0df40b (patch) | |
tree | 1e20c4d823f0ff734d77c54e96ab738f4186c740 /core | |
parent | 41bbe08c125bb3714aee862ec9dc55419c29986d (diff) | |
download | sttp-2761923dcf1ea49f7671cc2f18df9bd07f0df40b.tar.gz sttp-2761923dcf1ea49f7671cc2f18df9bd07f0df40b.tar.bz2 sttp-2761923dcf1ea49f7671cc2f18df9bd07f0df40b.zip |
Extracting FollowRedirectsHandler as a wrapper-handler
Diffstat (limited to 'core')
4 files changed, 80 insertions, 66 deletions
diff --git a/core/src/main/scala/com/softwaremill/sttp/FollowRedirectsHandler.scala b/core/src/main/scala/com/softwaremill/sttp/FollowRedirectsHandler.scala new file mode 100644 index 0000000..12aa0a8 --- /dev/null +++ b/core/src/main/scala/com/softwaremill/sttp/FollowRedirectsHandler.scala @@ -0,0 +1,72 @@ +package com.softwaremill.sttp + +import java.net.URI + +class FollowRedirectsHandler[R[_], S](delegate: SttpHandler[R, S]) + extends SttpHandler[R, S] { + + def send[T](request: Request[T, S]): R[Response[T]] = { + sendWithCounter(request, 0) + } + + private def sendWithCounter[T](request: Request[T, S], + redirects: Int): R[Response[T]] = { + val resp = delegate.send(request) + if (request.options.followRedirects) { + responseMonad.flatMap(resp) { response: Response[T] => + if (response.isRedirect) { + followRedirect(request, response, redirects) + } else { + responseMonad.unit(response) + } + } + } else { + resp + } + } + + private def followRedirect[T](request: Request[T, S], + response: Response[T], + redirects: Int): R[Response[T]] = { + + response.header(LocationHeader).fold(responseMonad.unit(response)) { loc => + if (redirects >= FollowRedirectsHandler.MaxRedirects) { + responseMonad.unit(Response(Left("Too many redirects"), 0, Nil, Nil)) + } else { + followRedirect(request, response, redirects, loc) + } + } + } + + private def followRedirect[T](request: Request[T, S], + response: Response[T], + redirects: Int, + loc: String): R[Response[T]] = { + + def isRelative(uri: String) = !uri.contains("://") + + val uri = if (isRelative(loc)) { + // using java's URI to resolve a relative URI + uri"${new URI(request.uri.toString).resolve(loc).toString}" + } else { + uri"$loc" + } + + val redirectResponse = + sendWithCounter(request.copy[Id, T, S](uri = uri), redirects + 1) + + responseMonad.map(redirectResponse) { rr => + val responseNoBody = + response.copy(body = response.body.right.map(_ => ())) + rr.copy(history = responseNoBody :: rr.history) + } + } + + override def close(): Unit = delegate.close() + + override def responseMonad: MonadError[R] = delegate.responseMonad +} + +object FollowRedirectsHandler { + private[sttp] val MaxRedirects = 32 +} diff --git a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala index ab10261..45a0448 100644 --- a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala +++ b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala @@ -12,8 +12,8 @@ import scala.annotation.tailrec import scala.io.Source import scala.collection.JavaConverters._ -object HttpURLConnectionHandler extends SttpHandler[Id, Nothing] { - override protected def doSend[T](r: Request[T, Nothing]): Response[T] = { +class HttpURLConnectionHandler extends SttpHandler[Id, Nothing] { + override def send[T](r: Request[T, Nothing]): Response[T] = { val c = new URL(r.uri.toString).openConnection().asInstanceOf[HttpURLConnection] c.setRequestMethod(r.method.m) diff --git a/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala b/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala index cc34102..248356d 100644 --- a/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala +++ b/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala @@ -1,7 +1,5 @@ package com.softwaremill.sttp -import java.net.URI - import scala.language.higherKinds /** @@ -11,74 +9,13 @@ import scala.language.higherKinds * if streaming requests/responses is not supported by this handler. */ trait SttpHandler[R[_], -S] { - def send[T](request: Request[T, S]): R[Response[T]] = { - sendWithCounter(request, 0) - } - - private def sendWithCounter[T](request: Request[T, S], - redirects: Int): R[Response[T]] = { - val resp = doSend(request) - if (request.options.followRedirects) { - responseMonad.flatMap(resp) { response: Response[T] => - if (response.isRedirect) { - followRedirect(request, response, redirects) - } else { - responseMonad.unit(response) - } - } - } else { - resp - } - } - - private def followRedirect[T](request: Request[T, S], - response: Response[T], - redirects: Int): R[Response[T]] = { - - response.header(LocationHeader).fold(responseMonad.unit(response)) { loc => - if (redirects >= SttpHandler.MaxRedirects) { - responseMonad.unit(Response(Left("Too many redirects"), 0, Nil, Nil)) - } else { - followRedirect(request, response, redirects, loc) - } - } - } - - private def followRedirect[T](request: Request[T, S], - response: Response[T], - redirects: Int, - loc: String): R[Response[T]] = { - - def isRelative(uri: String) = !uri.contains("://") - - val uri = if (isRelative(loc)) { - // using java's URI to resolve a relative URI - uri"${new URI(request.uri.toString).resolve(loc).toString}" - } else { - uri"$loc" - } - - val redirectResponse = - sendWithCounter(request.copy[Id, T, S](uri = uri), redirects + 1) - - responseMonad.map(redirectResponse) { rr => - val responseNoBody = - response.copy(body = response.body.right.map(_ => ())) - rr.copy(history = responseNoBody :: rr.history) - } - } + def send[T](request: Request[T, S]): R[Response[T]] def close(): Unit - protected def doSend[T](request: Request[T, S]): R[Response[T]] - /** * 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] } - -object SttpHandler { - private[sttp] val MaxRedirects = 32 -} diff --git a/core/src/main/scala/com/softwaremill/sttp/package.scala b/core/src/main/scala/com/softwaremill/sttp/package.scala index dc51ab2..d64acfe 100644 --- a/core/src/main/scala/com/softwaremill/sttp/package.scala +++ b/core/src/main/scala/com/softwaremill/sttp/package.scala @@ -266,4 +266,9 @@ package object sttp { implicit class UriContext(val sc: StringContext) extends AnyVal { def uri(args: Any*): Uri = UriInterpolator.interpolate(sc, args: _*) } + + // default handler + + val HttpURLConnectionHandler: SttpHandler[Id, Nothing] = + new FollowRedirectsHandler[Id, Nothing](new HttpURLConnectionHandler()) } |