Make servers HttpsRedirect exclude list more flexible

This commit is contained in:
Sergey Mashkov
2020-02-04 16:58:52 +03:00
parent 88f614cbdb
commit 3fea61a69f
3 changed files with 32 additions and 10 deletions

View File

@@ -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 <init> (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 <init> ()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
}

View File

@@ -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<String> = 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<String> = 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()

View File

@@ -88,7 +88,7 @@ class HttpsRedirectFeatureTest {
fun testRedirectHttpsExemption() {
withTestApplication {
application.install(HttpsRedirect) {
exemptions = listOf("/exempted")
excludePrefix("/exempted")
}
application.intercept(ApplicationCallPipeline.Fallback) {
call.respond("ok")