diff --git a/binary-compatibility-validator/reference-public-api/ktor-server-core.txt b/binary-compatibility-validator/reference-public-api/ktor-server-core.txt index bb7004451..82216e5a8 100644 --- a/binary-compatibility-validator/reference-public-api/ktor-server-core.txt +++ b/binary-compatibility-validator/reference-public-api/ktor-server-core.txt @@ -620,17 +620,18 @@ public final class io/ktor/features/HSTS$Feature : io/ktor/application/Applicati public final class io/ktor/features/HttpsRedirect { public static final field Feature Lio/ktor/features/HttpsRedirect$Feature; public fun (Lio/ktor/features/HttpsRedirect$Configuration;)V - public final fun getExemptions ()Ljava/util/List; + public final fun getExcludePredicates ()Ljava/util/List; public final fun getPermanent ()Z public final fun getRedirectPort ()I } public final class io/ktor/features/HttpsRedirect$Configuration { public fun ()V - public final fun getExemptions ()Ljava/util/List; + public final fun exclude (Lkotlin/jvm/functions/Function1;)V + public final fun excludePrefix (Ljava/lang/String;)V + public final fun getExcludePredicates ()Ljava/util/List; public final fun getPermanentRedirect ()Z public final fun getSslPort ()I - public final fun setExemptions (Ljava/util/List;)V public final fun setPermanentRedirect (Z)V public final fun setSslPort (I)V } diff --git a/ktor-server/ktor-server-core/jvm/src/io/ktor/features/HttpsRedirect.kt b/ktor-server/ktor-server-core/jvm/src/io/ktor/features/HttpsRedirect.kt index ab15bd426..3221684be 100644 --- a/ktor-server/ktor-server-core/jvm/src/io/ktor/features/HttpsRedirect.kt +++ b/ktor-server/ktor-server-core/jvm/src/io/ktor/features/HttpsRedirect.kt @@ -24,10 +24,11 @@ class HttpsRedirect(config: Configuration) { val permanent: Boolean = config.permanentRedirect /** - * Exempted paths + * The list of call predicates for redirect exclusion. + * Any call matching any of the predicates will not be redirected by this feature. */ - - val exemptions: List = config.exemptions + @KtorExperimentalAPI + val excludePredicates: List<(ApplicationCall) -> Boolean> = config.excludePredicates.toList() /** * Redirect feature configuration @@ -44,10 +45,29 @@ class HttpsRedirect(config: Configuration) { var permanentRedirect: Boolean = true /** - * Exempted path prefixes. Any request for a path starting with these prefixes will not be redirected. + * The list of call predicates for redirect exclusion. + * Any call matching any of the predicates will not be redirected by this feature. */ + @KtorExperimentalAPI + val excludePredicates: MutableList<(ApplicationCall) -> Boolean> = ArrayList() - var exemptions: List = listOf() + /** + * Exclude calls with paths matching the [pathPrefix] from being redirected to https by this feature. + */ + @KtorExperimentalAPI + fun excludePrefix(pathPrefix: String) { + exclude { call -> + call.request.origin.uri.startsWith(pathPrefix) + } + } + + /** + * Exclude calls matching the [predicate] from being redirected to https by this feature. + */ + @KtorExperimentalAPI + fun exclude(predicate: (call: ApplicationCall) -> Boolean) { + excludePredicates.add(predicate) + } } /** @@ -59,7 +79,8 @@ class HttpsRedirect(config: Configuration) { val feature = HttpsRedirect(Configuration().apply(configure)) pipeline.intercept(ApplicationCallPipeline.Features) { if (call.request.origin.scheme == "http" && - !feature.exemptions.any { call.request.origin.uri.startsWith(it) }) { + feature.excludePredicates.none { predicate -> predicate(call) } + ) { val redirectUrl = call.url { protocol = URLProtocol.HTTPS; port = feature.redirectPort } call.respondRedirect(redirectUrl, feature.permanent) finish() diff --git a/ktor-server/ktor-server-tests/jvm/test/io/ktor/tests/server/features/HttpsRedirectFeatureTest.kt b/ktor-server/ktor-server-tests/jvm/test/io/ktor/tests/server/features/HttpsRedirectFeatureTest.kt index 1de871ead..d0099adc2 100644 --- a/ktor-server/ktor-server-tests/jvm/test/io/ktor/tests/server/features/HttpsRedirectFeatureTest.kt +++ b/ktor-server/ktor-server-tests/jvm/test/io/ktor/tests/server/features/HttpsRedirectFeatureTest.kt @@ -88,7 +88,7 @@ class HttpsRedirectFeatureTest { fun testRedirectHttpsExemption() { withTestApplication { application.install(HttpsRedirect) { - exemptions = listOf("/exempted") + excludePrefix("/exempted") } application.intercept(ApplicationCallPipeline.Fallback) { call.respond("ok")