aboutsummaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authoradamw <adam@warski.org>2017-08-31 14:32:01 +0200
committeradamw <adam@warski.org>2017-08-31 14:32:01 +0200
commit71f6a1eeee412045cc08ce8894194573362cb8f0 (patch)
treec7618bb53f6e08c30df4e943f56d16fc1bfb80c1 /core/src
parent5bc89ddefab16dd814d0b716a72490451b697b32 (diff)
downloadsttp-71f6a1eeee412045cc08ce8894194573362cb8f0.tar.gz
sttp-71f6a1eeee412045cc08ce8894194573362cb8f0.tar.bz2
sttp-71f6a1eeee412045cc08ce8894194573362cb8f0.zip
Response.body is now an Either[String, T], to handle cases when the status code isn't 2xx
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala12
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/Response.scala23
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/package.scala8
-rw-r--r--core/src/test/scala/com/softwaremill/sttp/RequestTests.scala2
4 files changed, 39 insertions, 6 deletions
diff --git a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala
index 548dd9b..ddc1293 100644
--- a/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/HttpURLConnectionHandler.scala
@@ -191,9 +191,15 @@ object HttpURLConnectionHandler extends SttpHandler[Id, Nothing] {
.filter(_._1 != null)
.flatMap { case (k, vv) => vv.asScala.map((k, _)) }
val contentEncoding = Option(c.getHeaderField(ContentEncodingHeader))
- Response(readResponseBody(wrapInput(contentEncoding, is), responseAs),
- c.getResponseCode,
- headers)
+ val code = c.getResponseCode
+ val wrappedIs = wrapInput(contentEncoding, is)
+ val body = if (codeIsSuccess(code)) {
+ Right(readResponseBody(wrappedIs, responseAs))
+ } else {
+ Left(readResponseBody(wrappedIs, asString))
+ }
+
+ Response(body, code, headers)
}
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 44c39c3..5a3cfe3 100644
--- a/core/src/main/scala/com/softwaremill/sttp/Response.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/Response.scala
@@ -15,9 +15,18 @@ import scala.collection.JavaConverters._
import scala.collection.immutable.Seq
import scala.util.Try
-case class Response[T](body: T, code: Int, headers: Seq[(String, String)]) {
+/**
+ * @param body `Right(T)`, if the request was successful (status code 2xx).
+ * The body is then handled as specified in the request.
+ * `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`.
+ */
+case class Response[T](body: Either[String, T],
+ code: Int,
+ headers: Seq[(String, String)]) {
def is200: Boolean = code == 200
- def isSuccess: Boolean = code >= 200 && code < 300
+ def isSuccess: Boolean = codeIsSuccess(code)
def isRedirect: Boolean = code >= 300 && code < 400
def isClientError: Boolean = code >= 400 && code < 500
def isServerError: Boolean = code >= 500 && code < 600
@@ -34,6 +43,16 @@ case class Response[T](body: T, code: Int, headers: Seq[(String, String)]) {
def cookies: Seq[Cookie] =
headers(SetCookieHeader)
.flatMap(h => HttpCookie.parse(h).asScala.map(hc => Cookie.apply(hc, h)))
+
+ /**
+ * Get the body of the response. If the status code wasn't 2xx (and there's
+ * no body to return), an exception is thrown, containing the status code
+ * and the response from the server.
+ */
+ def unsafeBody: T = body match {
+ case Left(v) => throw new NoSuchElementException(s"Status code $code: $v")
+ case Right(v) => v
+ }
}
case class Cookie(name: String,
diff --git a/core/src/main/scala/com/softwaremill/sttp/package.scala b/core/src/main/scala/com/softwaremill/sttp/package.scala
index 3c4e844..24eb32c 100644
--- a/core/src/main/scala/com/softwaremill/sttp/package.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/package.scala
@@ -251,6 +251,14 @@ package object sttp {
transfer()
}
+ private[sttp] def codeIsSuccess(c: Int): Boolean = c >= 200 && c < 300
+
+ private[sttp] def concatByteBuffers(bb1: ByteBuffer, bb2: ByteBuffer): ByteBuffer =
+ ByteBuffer
+ .allocate(bb1.array().length + bb2.array().length)
+ .put(bb1)
+ .put(bb2)
+
// uri interpolator
implicit class UriContext(val sc: StringContext) extends AnyVal {
diff --git a/core/src/test/scala/com/softwaremill/sttp/RequestTests.scala b/core/src/test/scala/com/softwaremill/sttp/RequestTests.scala
index c6132c9..506167c 100644
--- a/core/src/test/scala/com/softwaremill/sttp/RequestTests.scala
+++ b/core/src/test/scala/com/softwaremill/sttp/RequestTests.scala
@@ -31,7 +31,7 @@ class RequestTests extends FlatSpec with Matchers {
it should "set cookies from a response" in {
val response =
- Response((),
+ Response(Right(()),
0,
List((SetCookieHeader, "k1=v1"), (SetCookieHeader, "k2=v2")))
sttp