aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoradamw <adam@warski.org>2017-07-15 21:16:28 +0200
committeradamw <adam@warski.org>2017-07-15 21:16:28 +0200
commit06e2ae994af39f77d8ee2b7ed367cba0936f35c4 (patch)
tree133491fc8e440a06330dc9be752460439d754c04
parente10115cabebd14f6838fa93e970c3b163d1a64a6 (diff)
downloadsttp-06e2ae994af39f77d8ee2b7ed367cba0936f35c4.tar.gz
sttp-06e2ae994af39f77d8ee2b7ed367cba0936f35c4.tar.bz2
sttp-06e2ae994af39f77d8ee2b7ed367cba0936f35c4.zip
Response as parameters
-rw-r--r--akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpSttpHandler.scala8
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala11
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/model/package.scala19
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/package.scala6
-rw-r--r--tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala25
5 files changed, 60 insertions, 9 deletions
diff --git a/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpSttpHandler.scala b/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpSttpHandler.scala
index a22c7cf..866aaad 100644
--- a/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpSttpHandler.scala
+++ b/akka-http-handler/src/main/scala/com/softwaremill/sttp/akkahttp/AkkaHttpSttpHandler.scala
@@ -58,17 +58,23 @@ class AkkaHttpSttpHandler(actorSystem: ActorSystem)
.runFold(ByteString(""))(_ ++ _)
.map(_.toArray[Byte])
+ def asString(enc: String) =
+ asByteArray.map(new String(_, enc))
+
rr match {
case IgnoreResponse =>
hr.discardEntityBytes()
Future.successful(())
case ResponseAsString(enc) =>
- asByteArray.map(new String(_, enc))
+ asString(enc)
case ResponseAsByteArray =>
asByteArray
+ case r @ ResponseAsParams(enc) =>
+ asString(enc).map(r.parse)
+
case r @ ResponseAsStream() =>
Future.successful(r.responseIsStream(hr.entity.dataBytes))
}
diff --git a/core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala b/core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala
index 4800a1b..dc6f8a2 100644
--- a/core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/HttpConnectionSttpHandler.scala
@@ -86,14 +86,17 @@ object HttpConnectionSttpHandler extends SttpHandler[Id, Nothing] {
}
private def readResponseBody[T](is: InputStream,
- responseAs: ResponseAs[T, Nothing]): T =
+ responseAs: ResponseAs[T, Nothing]): T = {
+ def asString(enc: String) = Source.fromInputStream(is, enc).mkString
+
responseAs match {
case IgnoreResponse =>
@tailrec def consume(): Unit = if (is.read() != -1) consume()
+
consume()
case ResponseAsString(enc) =>
- Source.fromInputStream(is, enc).mkString
+ asString(enc)
case ResponseAsByteArray =>
val os = new ByteArrayOutputStream
@@ -113,8 +116,12 @@ object HttpConnectionSttpHandler extends SttpHandler[Id, Nothing] {
os.toByteArray
+ case r @ ResponseAsParams(enc) =>
+ r.parse(asString(enc))
+
case ResponseAsStream() =>
// only possible when the user requests the response as a stream of Nothing. Oh well ...
throw new IllegalStateException()
}
+ }
}
diff --git a/core/src/main/scala/com/softwaremill/sttp/model/package.scala b/core/src/main/scala/com/softwaremill/sttp/model/package.scala
index 3504866..bd8b2e3 100644
--- a/core/src/main/scala/com/softwaremill/sttp/model/package.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/model/package.scala
@@ -1,10 +1,12 @@
package com.softwaremill.sttp
import java.io.InputStream
+import java.net.URLDecoder
import java.nio.ByteBuffer
import java.nio.file.Path
import scala.language.higherKinds
+import scala.collection.immutable.Seq
package object model {
case class Method(m: String) extends AnyVal
@@ -49,7 +51,22 @@ package object model {
case class ResponseAsString(encoding: String)
extends ResponseAs[String, Nothing]
object ResponseAsByteArray extends ResponseAs[Array[Byte], Nothing]
- // response as params
case class ResponseAsStream[T, S]()(implicit val responseIsStream: S =:= T)
extends ResponseAs[T, S]
+ case class ResponseAsParams(encoding: String)
+ extends ResponseAs[Seq[(String, String)], Nothing] {
+
+ def parse(s: String): Seq[(String, String)] = {
+ s.split("&")
+ .toList
+ .flatMap(kv =>
+ kv.split("=", 2) match {
+ case Array(k, v) =>
+ Some(
+ (URLDecoder.decode(k, encoding),
+ URLDecoder.decode(v, encoding)))
+ case _ => None
+ })
+ }
+ }
}
diff --git a/core/src/main/scala/com/softwaremill/sttp/package.scala b/core/src/main/scala/com/softwaremill/sttp/package.scala
index dfd1e3e..baf4061 100644
--- a/core/src/main/scala/com/softwaremill/sttp/package.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/package.scala
@@ -26,6 +26,12 @@ package object sttp {
ResponseAsString(encoding)
def responseAsByteArray: ResponseAs[Array[Byte], Nothing] =
ResponseAsByteArray
+ def responseAsParams: ResponseAs[Seq[(String, String)], Nothing] =
+ responseAsParams(Utf8)
+ def responseAsParams(
+ encoding: String): ResponseAs[Seq[(String, String)], Nothing] =
+ ResponseAsParams(encoding)
+
def responseAsStream[S]: ResponseAs[S, S] = ResponseAsStream[S, S]()
/**
diff --git a/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala b/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala
index 0606ae3..def843a 100644
--- a/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala
+++ b/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala
@@ -7,7 +7,7 @@ import java.time.{ZoneId, ZonedDateTime}
import akka.stream.ActorMaterializer
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
-import akka.http.scaladsl.model.DateTime
+import akka.http.scaladsl.model.{DateTime, FormData}
import akka.http.scaladsl.model.headers._
import akka.http.scaladsl.model.headers.CacheDirectives._
import akka.http.scaladsl.server.Directives._
@@ -33,9 +33,14 @@ class BasicTests
private val serverRoutes =
pathPrefix("echo") {
- path("form_params") {
+ pathPrefix("form_params") {
formFieldMap { params =>
- complete(paramsToString(params))
+ path("as_string") {
+ complete(paramsToString(params))
+ } ~
+ path("as_params") {
+ complete(FormData(params))
+ }
}
} ~ get {
parameterMap { params =>
@@ -161,6 +166,16 @@ class BasicTests
val fc = new String(response.body, "UTF-8")
fc should be(expectedPostEchoResponse)
}
+
+ name should "parse response as parameters" in {
+ val params = List("a" -> "b", "c" -> "d", "e=" -> "&f")
+ val response = sttp
+ .post(uri"$endpoint/echo/form_params/as_params")
+ .body(params: _*)
+ .send(responseAsParams)
+ .force()
+ response.body.toList should be(params)
+ }
}
def parameterTests(): Unit = {
@@ -221,7 +236,7 @@ class BasicTests
name should "post form data" in {
val response = sttp
- .post(uri"$endpoint/echo/form_params")
+ .post(uri"$endpoint/echo/form_params/as_string")
.body("a" -> "b", "c" -> "d")
.send(responseAsString)
.force()
@@ -230,7 +245,7 @@ class BasicTests
name should "post form data with special characters" in {
val response = sttp
- .post(uri"$endpoint/echo/form_params")
+ .post(uri"$endpoint/echo/form_params/as_string")
.body("a=" -> "/b", "c:" -> "/d")
.send(responseAsString)
.force()