aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoradamw <adam@warski.org>2017-08-31 15:11:01 +0200
committeradamw <adam@warski.org>2017-08-31 15:11:01 +0200
commit666755ede0d221c11c1eac6aac57ce3d18c42c8b (patch)
tree497fb484a20b9f3aa6c424e9b2d0fdccf27591ab
parent9ec0994878856743e54c4d1a38c0c80b318d7be7 (diff)
downloadsttp-666755ede0d221c11c1eac6aac57ce3d18c42c8b.tar.gz
sttp-666755ede0d221c11c1eac6aac57ce3d18c42c8b.tar.bz2
sttp-666755ede0d221c11c1eac6aac57ce3d18c42c8b.zip
Keep a history of redirect responses
-rw-r--r--akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpHandler.scala2
-rw-r--r--async-http-client-handler/src/main/scala/com/softwaremill/sttp/asynchttpclient/AsyncHttpClientHandler.scala3
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala2
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/Response.scala6
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala8
-rw-r--r--okhttp-handler/src/main/scala/com/softwaremill/sttp/okhttp/OkHttpClientHandler.scala2
-rw-r--r--tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala30
7 files changed, 43 insertions, 10 deletions
diff --git a/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpHandler.scala b/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpHandler.scala
index 35f8f81..a2695e2 100644
--- a/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpHandler.scala
+++ b/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpHandler.scala
@@ -48,7 +48,7 @@ class AkkaHttpHandler private (actorSystem: ActorSystem,
bodyFromAkka(asString, decodeAkkaResponse(hr)).map(Left(_))
}
- body.map(Response(_, code, headersFromAkka(hr)))
+ body.map(Response(_, code, headersFromAkka(hr), Nil))
}
}
diff --git a/async-http-client-handler/src/main/scala/com/softwaremill/sttp/asynchttpclient/AsyncHttpClientHandler.scala b/async-http-client-handler/src/main/scala/com/softwaremill/sttp/asynchttpclient/AsyncHttpClientHandler.scala
index 8b908cb..06124b7 100644
--- a/async-http-client-handler/src/main/scala/com/softwaremill/sttp/asynchttpclient/AsyncHttpClientHandler.scala
+++ b/async-http-client-handler/src/main/scala/com/softwaremill/sttp/asynchttpclient/AsyncHttpClientHandler.scala
@@ -252,7 +252,8 @@ abstract class AsyncHttpClientHandler[R[_], S](asyncHttpClient: AsyncHttpClient,
.iterator()
.asScala
.map(e => (e.getKey, e.getValue))
- .toList)
+ .toList,
+ Nil)
}
private def eagerResponseHandler(response: AsyncResponse) =
diff --git a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala
index ddc1293..24c93f4 100644
--- a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala
@@ -199,7 +199,7 @@ object HttpURLConnectionHandler extends SttpHandler[Id, Nothing] {
Left(readResponseBody(wrappedIs, asString))
}
- Response(body, code, headers)
+ Response(body, code, headers, Nil)
}
private def readResponseBody[T](is: InputStream,
diff --git a/core/src/main/scala/com/softwaremill/sttp/Response.scala b/core/src/main/scala/com/softwaremill/sttp/Response.scala
index 5a3cfe3..7551ee0 100644
--- a/core/src/main/scala/com/softwaremill/sttp/Response.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/Response.scala
@@ -21,10 +21,14 @@ import scala.util.Try
* `Left(String)`, if the request wasn't successful (status code
* 3xx, 4xx or 5xx). In this case, the response body is read into
* a `String`.
+ * @param history If redirects are followed, and there were redirects,
+ * contains responses for the intermediate requests.
+ * The first response (oldest) comes first.
*/
case class Response[T](body: Either[String, T],
code: Int,
- headers: Seq[(String, String)]) {
+ headers: Seq[(String, String)],
+ history: List[Response[Unit]]) {
def is200: Boolean = code == 200
def isSuccess: Boolean = codeIsSuccess(code)
def isRedirect: Boolean = code >= 300 && code < 400
diff --git a/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala b/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala
index 26464ba..2f44840 100644
--- a/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/SttpHandler.scala
@@ -38,7 +38,13 @@ trait SttpHandler[R[_], -S] {
uri"$loc"
}
- send(request.copy[Id, T, S](uri = uri))
+ val redirectResponse = send(request.copy[Id, T, S](uri = uri))
+
+ responseMonad.map(redirectResponse) { rr =>
+ val responseNoBody =
+ response.copy(body = response.body.right.map(_ => ()))
+ rr.copy(history = responseNoBody :: rr.history)
+ }
}
}
diff --git a/okhttp-handler/src/main/scala/com/softwaremill/sttp/okhttp/OkHttpClientHandler.scala b/okhttp-handler/src/main/scala/com/softwaremill/sttp/okhttp/OkHttpClientHandler.scala
index cef7054..eca7777 100644
--- a/okhttp-handler/src/main/scala/com/softwaremill/sttp/okhttp/OkHttpClientHandler.scala
+++ b/okhttp-handler/src/main/scala/com/softwaremill/sttp/okhttp/OkHttpClientHandler.scala
@@ -102,7 +102,7 @@ abstract class OkHttpHandler[R[_], S](client: OkHttpClient)
.asScala
.flatMap(name => res.headers().values(name).asScala.map((name, _)))
- responseMonad.map(body)(Response(_, res.code(), headers.toList))
+ responseMonad.map(body)(Response(_, res.code(), headers.toList, Nil))
}
private def responseHandler(res: OkHttpResponse) =
diff --git a/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala b/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala
index 39340de..f2639b5 100644
--- a/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala
+++ b/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala
@@ -155,6 +155,9 @@ class BasicTests
redirect("/redirect/r3", StatusCodes.PermanentRedirect)
} ~
path("r3") {
+ redirect("/redirect/r4", StatusCodes.Found)
+ } ~
+ path("r4") {
complete("819")
}
}
@@ -568,7 +571,8 @@ class BasicTests
def redirectTests(): Unit = {
val r1 = sttp.post(uri"$endpoint/redirect/r1")
val r2 = sttp.post(uri"$endpoint/redirect/r2")
- val r3response = "819"
+ val r3 = sttp.post(uri"$endpoint/redirect/r3")
+ val r4response = "819"
name should "not redirect when redirects shouldn't be followed (temporary)" in {
val resp = r1.followRedirects(false).send().force()
@@ -585,19 +589,37 @@ class BasicTests
name should "redirect when redirects should be followed" in {
val resp = r2.send().force()
resp.code should be(200)
- resp.unsafeBody should be(r3response)
+ resp.unsafeBody should be(r4response)
}
name should "redirect twice when redirects should be followed" in {
val resp = r1.send().force()
resp.code should be(200)
- resp.unsafeBody should be(r3response)
+ resp.unsafeBody should be(r4response)
}
name should "redirect when redirects should be followed, and the response is parsed" in {
val resp = r2.response(asString.map(_.toInt)).send().force()
resp.code should be(200)
- resp.unsafeBody should be(r3response.toInt)
+ resp.unsafeBody should be(r4response.toInt)
+ }
+
+ name should "keep a single history entry of redirect responses" in {
+ val resp = r3.send().force()
+ resp.code should be(200)
+ resp.unsafeBody should be(r4response)
+ resp.history should have size (1)
+ resp.history(0).code should be(302)
+ }
+
+ name should "keep whole history of redirect responses" in {
+ val resp = r1.send().force()
+ resp.code should be(200)
+ resp.unsafeBody should be(r4response)
+ resp.history should have size (3)
+ resp.history(0).code should be(307)
+ resp.history(1).code should be(308)
+ resp.history(2).code should be(302)
}
}
}