Skip to content

Commit 4b56eaf

Browse files
committed
Forwarded fixes & tests
1 parent a63e65f commit 4b56eaf

File tree

2 files changed

+41
-6
lines changed

2 files changed

+41
-6
lines changed

core/src/main/scala/sttp/model/headers/Forwarded.scala

+7-6
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ case class Forwarded(by: Option[String], `for`: Option[String], host: Option[Str
1212
*/
1313
override def toString: String = {
1414
val sb = new java.lang.StringBuilder()
15-
by.foreach(v => sb.append("by=").append(v).append(";"))
16-
`for`.foreach(v => sb.append("for=").append(v).append(";"))
17-
host.foreach(v => sb.append("host=").append(v).append(";"))
18-
proto.foreach(v => sb.append("proto=").append(v).append(";"))
15+
var separator = ""
16+
by.foreach { v => sb.append("by=").append(v); separator = ";" }
17+
`for`.foreach { v => sb.append(separator).append("for=").append(v); separator = ";" }
18+
host.foreach { v => sb.append(separator).append("host=").append(v); separator = ";" }
19+
proto.foreach { v => sb.append(separator).append("proto=").append(v) }
1920
sb.toString
2021
}
2122
}
@@ -33,7 +34,7 @@ object Forwarded {
3334
val parts = headerValue.split(";").map(_.trim).toList
3435
val kvPairs = parts.map { part =>
3536
part.split("=").map(_.trim).toList match {
36-
case key :: value :: Nil => Right(key -> value)
37+
case key :: value :: Nil => Right(key.toLowerCase -> value)
3738
case _ => Left(s"Invalid part: $part")
3839
}
3940
}
@@ -53,5 +54,5 @@ object Forwarded {
5354
}
5455

5556
/** Serialize a list of [[Forwarded]] headers to a single string. Each header will be separated by a comma. */
56-
def toString(headers: List[Forwarded]): String = headers.map(_.toString).mkString(", ")
57+
def toString(headers: List[Forwarded]): String = headers.map(_.toString).mkString(",")
5758
}

core/src/test/scala/sttp/model/headers/ForwardedTest.scala

+34
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ class ForwardedTest extends AnyFlatSpec with Matchers {
1010
actual shouldBe Right(List(Forwarded(Some("1.2.3.4"), Some("4.3.2.1"), Some("example.com"), Some("http"))))
1111
}
1212

13+
it should "parse a single header correctly, regardless of case of the directives" in {
14+
val actual = Forwarded.parse("By=1.2.3.4;For=4.3.2.1;Host=example.com;Proto=http")
15+
actual shouldBe Right(List(Forwarded(Some("1.2.3.4"), Some("4.3.2.1"), Some("example.com"), Some("http"))))
16+
}
17+
1318
it should "parse multiple headers correctly, when given as separate headers" in {
1419
val actual = Forwarded.parse(List("by=1.2.3.4;for=4.3.2.1", "host=example.com;proto=https"))
1520
actual shouldBe Right(
@@ -44,4 +49,33 @@ class ForwardedTest extends AnyFlatSpec with Matchers {
4449
val actual = Forwarded.parse("by=1.2.3.4;for")
4550
actual shouldBe Left("Invalid part: for")
4651
}
52+
53+
it should "serialize the header to a string" in {
54+
val actual =
55+
Forwarded.toString(List(Forwarded(Some("1.2.3.4"), Some("4.3.2.1"), Some("example.com"), Some("http"))))
56+
actual shouldBe "by=1.2.3.4;for=4.3.2.1;host=example.com;proto=http"
57+
}
58+
59+
it should "serialize multiple headers to a string" in {
60+
val actual =
61+
Forwarded.toString(
62+
List(Forwarded(Some("1.2.3.4"), None, None, None), Forwarded(Some("4.3.2.1"), None, None, None))
63+
)
64+
actual shouldBe "by=1.2.3.4,by=4.3.2.1"
65+
}
66+
67+
it should "parse ipv6 addresses in For" in {
68+
val actual = Forwarded.parse("""For="[2001:db8:cafe::17]:4711"""")
69+
actual shouldBe Right(List(Forwarded(None, Some("\"[2001:db8:cafe::17]:4711\""), None, None)))
70+
}
71+
72+
it should "parse multiple ipv4 addresses" in {
73+
val actual = Forwarded.parse("for=192.0.2.43, for=198.51.100.17")
74+
actual shouldBe Right(
75+
List(
76+
Forwarded(None, Some("192.0.2.43"), None, None),
77+
Forwarded(None, Some("198.51.100.17"), None, None)
78+
)
79+
)
80+
}
4781
}

0 commit comments

Comments
 (0)