Skip to content

Commit

Permalink
KTOR-7278: Fix evaluation of accept header with wildcards (#4264)
Browse files Browse the repository at this point in the history
  • Loading branch information
anton-erofeev authored Nov 13, 2024
1 parent bd7b619 commit 5477790
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,9 @@ public data class HttpMultiAcceptRouteSelector(
return RouteSelectorEvaluation.Missing
}

val header = parsedHeaders.firstOrNull { header -> contentTypes.any { it.match(header.value) } }
val header = parsedHeaders.firstOrNull { header ->
contentTypes.any { it.isCompatibleWith(ContentType.parse(header.value)) }
}
if (header != null) {
return RouteSelectorEvaluation.Success(header.quality)
}
Expand Down Expand Up @@ -661,3 +663,10 @@ internal fun evaluatePathSegmentParameter(
segmentIncrement = 1
)
}

private fun ContentType.isCompatibleWith(other: ContentType): Boolean = when {
this.contentType == "*" && this.contentSubtype == "*" -> true
other.contentType == "*" && other.contentSubtype == "*" -> true
this.contentSubtype == "*" -> other.match(this)
else -> this.match(other)
}
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,75 @@ class RoutingProcessingTest {
}
}

@Test
fun testRoutingAcceptContentSubtypeWildcard() = testApplication {
routing {
route("image") {
accept(ContentType.Image.Any) {
get { call.respondText { "Image" } }
}
}
route("any") {
accept(ContentType.Any) {
get { call.respondText { "Any" } }
}
}
}

on("making request to /image with Accept image/png") {
client.get("/image") {
header(HttpHeaders.Accept, ContentType.Image.PNG)
}.let {
assertEquals(HttpStatusCode.OK, it.status)
assertEquals("Image", it.bodyAsText())
}
}

on("making request to /image with Accept */*") {
client.get("/image") {
header(HttpHeaders.Accept, ContentType.Any)
}.let {
assertEquals(HttpStatusCode.OK, it.status)
assertEquals("Image", it.bodyAsText())
}
}

on("making request to /any with Accept image/png") {
client.get("/any") {
header(HttpHeaders.Accept, ContentType.Image.PNG)
}.let {
assertEquals(HttpStatusCode.OK, it.status)
assertEquals("Any", it.bodyAsText())
}
}

on("making request to /any with Accept image/*") {
client.get("/any") {
header(HttpHeaders.Accept, ContentType.Image.Any)
}.let {
assertEquals(HttpStatusCode.OK, it.status)
assertEquals("Any", it.bodyAsText())
}
}

on("making request to /any with Accept */*") {
client.get("/any") {
header(HttpHeaders.Accept, ContentType.Any)
}.let {
assertEquals(HttpStatusCode.OK, it.status)
assertEquals("Any", it.bodyAsText())
}
}

on("making request to /image with Accept text/plain") {
client.get("/image") {
header(HttpHeaders.Accept, ContentType.Text.Plain)
}.let {
assertEquals(HttpStatusCode.BadRequest, it.status)
}
}
}

@Test
fun testMostSpecificSelected() = testApplication {
var path = ""
Expand Down

0 comments on commit 5477790

Please sign in to comment.