aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoradamw <adam@warski.org>2017-10-31 14:46:38 +0100
committeradamw <adam@warski.org>2017-10-31 15:48:19 +0100
commit2dcc31ba8fec394b37801a4fb505fd73c33c14b1 (patch)
tree89428bd80061aaabb55ea9b7e7b9a1daee9c15eb
parenta2a6db30bceb7a798ad36673cfcbe61088c7083f (diff)
downloadsttp-2dcc31ba8fec394b37801a4fb505fd73c33c14b1.tar.gz
sttp-2dcc31ba8fec394b37801a4fb505fd73c33c14b1.tar.bz2
sttp-2dcc31ba8fec394b37801a4fb505fd73c33c14b1.zip
#40: properly concatenating expression/token sequences in uri interpolator
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala45
-rw-r--r--core/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala7
2 files changed, 46 insertions, 6 deletions
diff --git a/core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala b/core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala
index f1e6beb..fe19358 100644
--- a/core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala
@@ -437,11 +437,46 @@ object UriInterpolator {
case x => Some(x.toString)
}
- private def tokensToStringSeq(t: Vector[Token]): Seq[String] = t.flatMap {
- case ExpressionToken(s: Seq[_]) => s.flatMap(anyToStringOpt).toVector
- case ExpressionToken(e) => anyToStringOpt(e).toVector
- case StringToken(s) => Vector(decode(s))
- case _ => Vector.empty
+ private def tokensToStringSeq(tokens: Vector[Token]): Seq[String] = {
+ /*
+ #40: when converting tokens to a string sequence, we have to look at
+ groups of string/expression (value) tokens separated by others. If there
+ are multiple tokens in each such group, their string representations
+ should be concatenated (corresponds to e.g. $x$y). A single
+ collection-valued token should be expanded.
+ */
+
+ def isValueToken(t: Token) = t match {
+ case ExpressionToken(_) => true
+ case StringToken(_) => true
+ case _ => false
+ }
+
+ @tailrec
+ def doToSeq(ts: Vector[Token], acc: Vector[String]): Seq[String] = {
+ val tsWithValuesPrefix = ts.dropWhile(to => !isValueToken(to))
+ val (valueTs, tailTs) = tsWithValuesPrefix.span(isValueToken)
+
+ valueTs match {
+ case Vector() => acc // tailTs must be empty then as well
+ case Vector(ExpressionToken(s: Seq[_])) =>
+ doToSeq(tailTs, acc ++ s.flatMap(anyToStringOpt).toVector)
+ case _ =>
+ val values = valueTs
+ .flatMap {
+ case ExpressionToken(e) => anyToStringOpt(e)
+ case StringToken(s) => Some(decode(s))
+ case _ => None
+ }
+
+ val strToAdd =
+ if (values.isEmpty) None else Some(values.mkString(""))
+
+ doToSeq(tailTs, acc ++ strToAdd)
+ }
+ }
+
+ doToSeq(tokens, Vector.empty)
}
private def tokensToStringOpt(t: Vector[Token]): Option[String] = t match {
diff --git a/core/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala b/core/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala
index 9fc2d3a..acfa9d4 100644
--- a/core/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala
+++ b/core/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala
@@ -41,6 +41,9 @@ class UriInterpolatorTests extends FunSuite with Matchers {
"authority" -> List(
(uri"http://$v1.com", s"http://$v1.com"),
(uri"http://$v2.com", s"http://$v2encoded.com"),
+ (uri"http://$v1.$v2.com", s"http://$v1.$v2encoded.com"),
+ (uri"http://$v1$v2.com", s"http://$v1$v2encoded.com"),
+ (uri"http://z$v1.com", s"http://z$v1.com"),
(uri"http://$None.example.com", s"http://example.com"),
(uri"http://$None.$None.example.com", s"http://example.com"),
(uri"http://${Some("sub")}.example.com", s"http://sub.example.com"),
@@ -78,7 +81,9 @@ class UriInterpolatorTests extends FunSuite with Matchers {
(uri"http://example.com?x=$v1", s"http://example.com?x=$v1"),
(uri"http://example.com/?x=$v1", s"http://example.com/?x=$v1"),
(uri"http://example.com?x=$v2", s"http://example.com?x=$v2queryEncoded"),
- (uri"http://example.com?x=$v3", s"http://example.com?x=$v3encoded")
+ (uri"http://example.com?x=$v3", s"http://example.com?x=$v3encoded"),
+ (uri"http://example.com?x=$v1$v1", s"http://example.com?x=$v1$v1"),
+ (uri"http://example.com?x=z$v1", s"http://example.com?x=z$v1")
),
"query parameter without value" -> List(
(uri"http://example.com?$v1", s"http://example.com?$v1"),