Skip to content

Commit e908612

Browse files
Fix auto head response feature (#1835).
1 parent a9c1c7b commit e908612

File tree

5 files changed

+36
-6
lines changed

5 files changed

+36
-6
lines changed

ktor-http/api/ktor-http.api

+7-3
Original file line numberDiff line numberDiff line change
@@ -579,13 +579,17 @@ public final class io/ktor/http/HttpMessagePropertiesKt {
579579

580580
public final class io/ktor/http/HttpMethod {
581581
public static final field Companion Lio/ktor/http/HttpMethod$Companion;
582-
public fun <init> (Ljava/lang/String;)V
582+
public fun <init> (Ljava/lang/String;Ljava/util/List;)V
583+
public synthetic fun <init> (Ljava/lang/String;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
583584
public final fun component1 ()Ljava/lang/String;
584-
public final fun copy (Ljava/lang/String;)Lio/ktor/http/HttpMethod;
585-
public static synthetic fun copy$default (Lio/ktor/http/HttpMethod;Ljava/lang/String;ILjava/lang/Object;)Lio/ktor/http/HttpMethod;
585+
public final fun component2 ()Ljava/util/List;
586+
public final fun copy (Ljava/lang/String;Ljava/util/List;)Lio/ktor/http/HttpMethod;
587+
public static synthetic fun copy$default (Lio/ktor/http/HttpMethod;Ljava/lang/String;Ljava/util/List;ILjava/lang/Object;)Lio/ktor/http/HttpMethod;
586588
public fun equals (Ljava/lang/Object;)Z
589+
public final fun getAggregate ()Ljava/util/List;
587590
public final fun getValue ()Ljava/lang/String;
588591
public fun hashCode ()I
592+
public final fun match (Lio/ktor/http/HttpMethod;)Z
589593
public fun toString ()Ljava/lang/String;
590594
}
591595

ktor-http/common/src/io/ktor/http/HttpMethod.kt

+15-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,25 @@
44

55
package io.ktor.http
66

7+
import io.ktor.util.*
8+
79
/**
810
* Represents an HTTP method (verb)
911
* @property value contains method name
1012
*/
11-
data class HttpMethod(val value: String) {
13+
data class HttpMethod(val value: String, @InternalAPI val aggregate: List<HttpMethod> = listOf()) {
14+
/**
15+
* Checks if the specified HTTP [method] matches this instance of the HTTP method. Specified method matches if it's
16+
* equal to this HTTP method or at least one of methods this HTTP method aggregates.
17+
*/
18+
fun match(method: HttpMethod): Boolean {
19+
if (this == method) {
20+
return true
21+
}
22+
23+
return aggregate.contains(method) || method.aggregate.contains(this)
24+
}
25+
1226
@Suppress("KDocMissingDocumentation", "PublicApiImplicitType")
1327
companion object {
1428
val Get = HttpMethod("GET")

ktor-server/ktor-server-core/jvm/src/io/ktor/features/AutoHeadResponse.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ object AutoHeadResponse : ApplicationFeature<ApplicationCallPipeline, Unit, Unit
3333

3434
// Pretend the request was with GET method so that all normal routes and interceptors work
3535
// but in the end we will drop the content
36-
call.mutableOriginConnectionPoint.method = HttpMethod.Get
36+
call.mutableOriginConnectionPoint.method = HttpMethod(
37+
"GET_OR_HEAD",
38+
listOf(HttpMethod.Get, HttpMethod.Head)
39+
)
3740
}
3841
}
3942
}

ktor-server/ktor-server-core/jvm/src/io/ktor/routing/RouteSelector.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ data class AndRouteSelector(val first: RouteSelector, val second: RouteSelector)
349349
*/
350350
data class HttpMethodRouteSelector(val method: HttpMethod) : RouteSelector(RouteSelectorEvaluation.qualityParameter) {
351351
override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation {
352-
if (context.call.request.httpMethod == method)
352+
if (context.call.request.httpMethod.match(method))
353353
return RouteSelectorEvaluation.Constant
354354
return RouteSelectorEvaluation.Failed
355355
}

ktor-server/ktor-server-tests/jvm/test/io/ktor/tests/server/features/HeadTest.kt

+9
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class HeadTest {
2626
call.response.header("M", "1")
2727
call.respond("Hello")
2828
}
29+
30+
head("/head") {
31+
call.respond(HttpStatusCode.OK)
32+
}
2933
}
3034

3135
handleRequest(HttpMethod.Get, "/").let { call ->
@@ -39,6 +43,11 @@ class HeadTest {
3943
assertNull(call.response.content)
4044
assertEquals("1", call.response.headers["M"])
4145
}
46+
47+
handleRequest(HttpMethod.Head, "/head").let { call ->
48+
assertEquals(HttpStatusCode.OK, call.response.status())
49+
assertNull(call.response.content)
50+
}
4251
}
4352
}
4453

0 commit comments

Comments
 (0)