diff options
author | adamw <adam@warski.org> | 2017-08-31 15:11:01 +0200 |
---|---|---|
committer | adamw <adam@warski.org> | 2017-08-31 15:11:01 +0200 |
commit | 666755ede0d221c11c1eac6aac57ce3d18c42c8b (patch) | |
tree | 497fb484a20b9f3aa6c424e9b2d0fdccf27591ab | |
parent | 9ec0994878856743e54c4d1a38c0c80b318d7be7 (diff) | |
download | sttp-666755ede0d221c11c1eac6aac57ce3d18c42c8b.tar.gz sttp-666755ede0d221c11c1eac6aac57ce3d18c42c8b.tar.bz2 sttp-666755ede0d221c11c1eac6aac57ce3d18c42c8b.zip |
Keep a history of redirect responses
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) } } } |