From c73dd267e7efdcfcaf81147b5cf846cfd9eb4c30 Mon Sep 17 00:00:00 2001 From: Alexis Cote Date: Thu, 11 Jul 2024 20:54:38 -0400 Subject: [PATCH] fix(api-formats): Gracefully handle invalid Accept header quality Wrap `toDouble` operation in a try to handle cases where invalid string cannot be converted to a double. --- core/src/main/scala/org/scalatra/ApiFormats.scala | 8 ++++---- core/src/test/scala/org/scalatra/ApiFormatsSpec.scala | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/core/src/main/scala/org/scalatra/ApiFormats.scala b/core/src/main/scala/org/scalatra/ApiFormats.scala index dc4bbd3ec..af559ab10 100644 --- a/core/src/main/scala/org/scalatra/ApiFormats.scala +++ b/core/src/main/scala/org/scalatra/ApiFormats.scala @@ -3,11 +3,11 @@ package org.scalatra import java.util.Locale.ENGLISH import java.util.concurrent.ConcurrentHashMap import org.scalatra.ServletCompat.http.{ HttpServletRequest, HttpServletResponse } +import org.scalatra.util.RicherString.* -import org.scalatra.util.RicherString._ - -import scala.jdk.CollectionConverters._ +import scala.jdk.CollectionConverters.* import scala.collection.concurrent +import scala.util.Try object ApiFormats { @@ -113,7 +113,7 @@ trait ApiFormats extends ScalatraBase { private def parseAcceptHeader(implicit request: HttpServletRequest): List[String] = { def isValidQPair(a: Array[String]) = { - a.length == 2 && a(0) == "q" && validRange.contains(a(1).toDouble) + a.length == 2 && a(0) == "q" && Try(a(1).toDouble).toOption.exists(validRange.contains) } request.headers.get("Accept") map { s => diff --git a/core/src/test/scala/org/scalatra/ApiFormatsSpec.scala b/core/src/test/scala/org/scalatra/ApiFormatsSpec.scala index 28fdf0303..9e48d6705 100644 --- a/core/src/test/scala/org/scalatra/ApiFormatsSpec.scala +++ b/core/src/test/scala/org/scalatra/ApiFormatsSpec.scala @@ -84,6 +84,13 @@ class ApiFormatsSpec extends MutableScalatraSpec { body must_== "txt" } } + + "when the priory value is not a double the parser should ignore the broken priority" in { + get("/hello", headers = Map("Accept" -> "application/json; q=0.8 oops, text/plain, */*")) { + response.getContentType() must startWith("text/plain") + body must_== "txt" + } + } } } }