diff options
author | adamw <adam@warski.org> | 2017-07-15 21:16:28 +0200 |
---|---|---|
committer | adamw <adam@warski.org> | 2017-07-15 21:16:28 +0200 |
commit | 06e2ae994af39f77d8ee2b7ed367cba0936f35c4 (patch) | |
tree | 133491fc8e440a06330dc9be752460439d754c04 | |
parent | e10115cabebd14f6838fa93e970c3b163d1a64a6 (diff) | |
download | sttp-06e2ae994af39f77d8ee2b7ed367cba0936f35c4.tar.gz sttp-06e2ae994af39f77d8ee2b7ed367cba0936f35c4.tar.bz2 sttp-06e2ae994af39f77d8ee2b7ed367cba0936f35c4.zip |
Response as parameters
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() |