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 8fa833417d..38d85309df 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 18310caa18..c17b49def6 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")