This is an automated email from the ASF dual-hosted git repository.

pjfanning pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko-http.git


The following commit(s) were added to refs/heads/main by this push:
     new 08e174c4c fix: use root locale when looking up a response header by 
name in RouteTest (#1223)
08e174c4c is described below

commit 08e174c4ce2a1bf6c8371bf75e572093840bbd54
Author: PJ Fanning <[email protected]>
AuthorDate: Mon Aug 24 12:18:44 2026 +0100

    fix: use root locale when looking up a response header by name in RouteTest 
(#1223)
    
    Motivation:
    `RouteTest#header(name: String)` lowercased the given header name with the
    JVM default locale before comparing it to `HttpHeader#lowercaseName`, which
    is built with `toRootLowerCase`. Under a Turkish locale 
`"If-Match".toLowerCase`
    yields a dotless i, so the lookup silently returned `None` for any header 
name
    containing a capital `I`. The javadsl equivalent (`TestRouteResult`) already
    uses `toRootLowerCase`.
    
    Modification:
    Use `pekko.util.Helpers.toRootLowerCase` in `RouteTest#header(name)`.
    
    Result:
    Header lookup by name in the Scala testkit is locale independent and matches
    the javadsl behaviour.
    
    Tests:
    - sbt "http-testkit / Test / testOnly 
org.apache.pekko.http.scaladsl.testkit.ScalatestRouteTestSpec" - passes with 
the fix; the new test fails without it
    - scalafmt --mode diff-ref=origin/main - clean
    - sbt +mimaReportBinaryIssues - not run; method body change only, no API or 
binary shape change
    
    References:
    None - found while auditing the code base for locale sensitive lowercasing
---
 .../pekko/http/scaladsl/testkit/RouteTest.scala     |  3 ++-
 .../scaladsl/testkit/ScalatestRouteTestSpec.scala   | 21 +++++++++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git 
a/http-testkit/src/main/scala/org/apache/pekko/http/scaladsl/testkit/RouteTest.scala
 
b/http-testkit/src/main/scala/org/apache/pekko/http/scaladsl/testkit/RouteTest.scala
index 8fa833417..38d85309d 100644
--- 
a/http-testkit/src/main/scala/org/apache/pekko/http/scaladsl/testkit/RouteTest.scala
+++ 
b/http-testkit/src/main/scala/org/apache/pekko/http/scaladsl/testkit/RouteTest.scala
@@ -36,6 +36,7 @@ import pekko.stream.{ Materializer, SystemMaterializer }
 import pekko.stream.scaladsl.Source
 import pekko.testkit.TestKit
 import pekko.util.ConstantFun
+import pekko.util.Helpers.toRootLowerCase
 
 import com.typesafe.config.{ Config, ConfigFactory }
 
@@ -96,7 +97,7 @@ trait RouteTest extends RequestBuilding with 
WSTestRequestBuilding with RouteTes
   def charset: HttpCharset = charsetOption.getOrElse(sys.error("Binary entity 
does not have charset"))
   def headers: immutable.Seq[HttpHeader] = rawResponse.headers
   def header[T >: Null <: HttpHeader: ClassTag]: Option[T] = 
rawResponse.header[T](implicitly[ClassTag[T]])
-  def header(name: String): Option[HttpHeader] = 
rawResponse.headers.find(_.is(name.toLowerCase))
+  def header(name: String): Option[HttpHeader] = 
rawResponse.headers.find(_.is(toRootLowerCase(name)))
   def status: StatusCode = rawResponse.status
 
   def closingExtension: String = chunks.lastOption match {
diff --git 
a/http-testkit/src/test/scala/org/apache/pekko/http/scaladsl/testkit/ScalatestRouteTestSpec.scala
 
b/http-testkit/src/test/scala/org/apache/pekko/http/scaladsl/testkit/ScalatestRouteTestSpec.scala
index 18310caa1..c17b49def 100644
--- 
a/http-testkit/src/test/scala/org/apache/pekko/http/scaladsl/testkit/ScalatestRouteTestSpec.scala
+++ 
b/http-testkit/src/test/scala/org/apache/pekko/http/scaladsl/testkit/ScalatestRouteTestSpec.scala
@@ -13,6 +13,8 @@
 
 package org.apache.pekko.http.scaladsl.testkit
 
+import java.util.Locale
+
 import scala.concurrent.Await
 import scala.concurrent.Future
 import scala.concurrent.duration._
@@ -57,6 +59,25 @@ class ScalatestRouteTestSpec extends AnyFreeSpec with 
Matchers with ScalatestRou
       }
     }
 
+    "a header lookup by name that is unaffected by the turkish-i problem" in {
+      val previousLocale = Locale.getDefault
+      try {
+        Locale.setDefault(new Locale("tr", "TR"))
+        // in the turkish locale 'I'.toLowerCase is a dotless i, so a 
default-locale
+        // lowercasing of 'If-Match' would not match the header's lowercaseName
+        val ifMatchHeader = RawHeader("If-Match", "\"xyzzy\"")
+        Get() ~> {
+          respondWithHeader(ifMatchHeader) {
+            complete("abc")
+          }
+        } ~> check {
+          header("If-Match") shouldEqual Some(ifMatchHeader)
+        }
+      } finally {
+        Locale.setDefault(previousLocale)
+      }
+    }
+
     "a test using ~!> and some checks" in {
       // raw here, should have been parsed into modelled header when going 
through an actual server when using `~!>`
       val extraHeader = RawHeader("X-Forwarded-Proto", "abc")


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to