aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authoradamw <adam@warski.org>2017-09-04 16:27:43 +0200
committeradamw <adam@warski.org>2017-09-04 16:27:43 +0200
commit2761923dcf1ea49f7671cc2f18df9bd07f0df40b (patch)
tree1e20c4d823f0ff734d77c54e96ab738f4186c740 /core
parent41bbe08c125bb3714aee862ec9dc55419c29986d (diff)
downloadsttp-2761923dcf1ea49f7671cc2f18df9bd07f0df40b.tar.gz
sttp-2761923dcf1ea49f7671cc2f18df9bd07f0df40b.tar.bz2
sttp-2761923dcf1ea49f7671cc2f18df9bd07f0df40b.zip
Extracting FollowRedirectsHandler as a wrapper-handler
Diffstat (limited to 'core')
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/FollowRedirectsHandler.scala72
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala4
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala65
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/package.scala5
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())
}