aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoradamw <adam@warski.org>2017-11-27 11:59:43 +0100
committeradamw <adam@warski.org>2017-11-27 11:59:43 +0100
commitfc07b4ac1c67c9a096fe1d63bf5049eabff8b6c1 (patch)
tree38472bed61b345dd92ce68969198bb517b165394
parent54722c73e472178f96416fbff8929d9a699d3e03 (diff)
downloadsttp-fc07b4ac1c67c9a096fe1d63bf5049eabff8b6c1.tar.gz
sttp-fc07b4ac1c67c9a096fe1d63bf5049eabff8b6c1.tar.bz2
sttp-fc07b4ac1c67c9a096fe1d63bf5049eabff8b6c1.zip
Properly handling ipv6 in the uri interpolator
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala39
-rw-r--r--core/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala5
2 files changed, 35 insertions, 9 deletions
diff --git a/core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala b/core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala
index f0dbcba..fba3eaa 100644
--- a/core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/UriInterpolator.scala
@@ -129,6 +129,17 @@ object UriInterpolator {
}
object Authority extends Tokenizer {
+ private val IpV6InAuthorityPattern = "\\[[0-9a-fA-F:]+\\]".r
+
+ private def ipv6parser(a: String): Option[Vector[Token]] = {
+ a match {
+ case IpV6InAuthorityPattern() =>
+ // removing the [] which are used to surround ipv6 adresses in URLs
+ Some(Vector(StringToken(a.substring(1, a.length - 1))))
+ case _ => None
+ }
+ }
+
override def tokenize(s: String): (Tokenizer, Vector[Token]) =
tokenizeTerminatedFragment(
s,
@@ -136,7 +147,8 @@ object UriInterpolator {
Set('/', '?', '#'),
Map(':' -> ColonInAuthority,
'@' -> AtInAuthority,
- '.' -> DotInAuthority)
+ '.' -> DotInAuthority),
+ ipv6parser
)
}
@@ -172,19 +184,28 @@ object UriInterpolator {
*
* The rest of the string, after the terminators, is tokenized using
* a tokenizer determined by the type of the terminator.
+ *
+ * @param extraFragmentParser A context-specific parser which is given the
+ * option to tokenize a fragment (without terminators).
*/
private def tokenizeTerminatedFragment(
s: String,
current: Tokenizer,
terminators: Set[Char],
- separatorsToTokens: Map[Char, Token]): (Tokenizer, Vector[Token]) = {
+ separatorsToTokens: Map[Char, Token],
+ extraFragmentParser: String => Option[Vector[Token]] = _ => None)
+ : (Tokenizer, Vector[Token]) = {
def tokenizeFragment(f: String): Vector[Token] = {
- splitPreserveSeparators(f, separatorsToTokens.keySet).map { t =>
- t.headOption.flatMap(separatorsToTokens.get) match {
- case Some(token) => token
- case None => StringToken(t)
- }
+ extraFragmentParser(f) match {
+ case None =>
+ splitPreserveSeparators(f, separatorsToTokens.keySet).map { t =>
+ t.headOption.flatMap(separatorsToTokens.get) match {
+ case Some(token) => token
+ case None => StringToken(t)
+ }
+ }
+ case Some(tt) => tt
}
}
@@ -316,9 +337,9 @@ object UriInterpolator {
case e: ExpressionToken =>
val es = tokensToString(Vector(e))
es.split(":", 2) match {
- case Array(_) => Vector(e)
- case Array(h, p) =>
+ case Array(h, p) if p.matches("\\d+") =>
Vector(StringToken(h), ColonInAuthority, StringToken(p))
+ case _ => Vector(e)
}
case t => Vector(t)
}
diff --git a/core/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala b/core/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala
index 1d6f838..92c90c3 100644
--- a/core/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala
+++ b/core/src/test/scala/com/softwaremill/sttp/UriInterpolatorTests.scala
@@ -60,6 +60,11 @@ class UriInterpolatorTests extends FunSuite with Matchers {
(uri"http://192.168.1.2/x", s"http://192.168.1.2/x"),
(uri"http://${"192.168.1.2"}/x", s"http://192.168.1.2/x")
),
+ "ipv6" -> List(
+ (uri"http://[::1]/x", s"http://[::1]/x"),
+ (uri"http://${"::1"}/x", s"http://[::1]/x"),
+ (uri"http://${"::1"}:${8080}/x", s"http://[::1]:8080/x")
+ ),
"ports" -> List(
(uri"http://example.com:8080", s"http://example.com:8080"),
(uri"http://example.com:${8080}", s"http://example.com:8080"),