Skip to content

Commit 0665736

Browse files
authored
KTOR-7483 Allow auth header when client is not shared (#4368)
1 parent e307968 commit 0665736

4 files changed

Lines changed: 25 additions & 47 deletions

File tree

ktor-client/ktor-client-core/api/ktor-client-core.api

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ public final class io/ktor/client/plugins/api/TransformResponseBodyContext {
598598

599599
public final class io/ktor/client/plugins/cache/HttpCache {
600600
public static final field Companion Lio/ktor/client/plugins/cache/HttpCache$Companion;
601-
public synthetic fun <init> (Lio/ktor/client/plugins/cache/storage/HttpCacheStorage;Lio/ktor/client/plugins/cache/storage/HttpCacheStorage;Lio/ktor/client/plugins/cache/storage/CacheStorage;Lio/ktor/client/plugins/cache/storage/CacheStorage;ZZZLkotlin/jvm/internal/DefaultConstructorMarker;)V
601+
public synthetic fun <init> (Lio/ktor/client/plugins/cache/storage/HttpCacheStorage;Lio/ktor/client/plugins/cache/storage/HttpCacheStorage;Lio/ktor/client/plugins/cache/storage/CacheStorage;Lio/ktor/client/plugins/cache/storage/CacheStorage;ZZLkotlin/jvm/internal/DefaultConstructorMarker;)V
602602
}
603603

604604
public final class io/ktor/client/plugins/cache/HttpCache$Companion : io/ktor/client/plugins/HttpClientPlugin {
@@ -612,13 +612,11 @@ public final class io/ktor/client/plugins/cache/HttpCache$Companion : io/ktor/cl
612612

613613
public final class io/ktor/client/plugins/cache/HttpCache$Config {
614614
public fun <init> ()V
615-
public final fun getCacheRequestWithAuth ()Z
616615
public final fun getPrivateStorage ()Lio/ktor/client/plugins/cache/storage/HttpCacheStorage;
617616
public final fun getPublicStorage ()Lio/ktor/client/plugins/cache/storage/HttpCacheStorage;
618617
public final fun isShared ()Z
619618
public final fun privateStorage (Lio/ktor/client/plugins/cache/storage/CacheStorage;)V
620619
public final fun publicStorage (Lio/ktor/client/plugins/cache/storage/CacheStorage;)V
621-
public final fun setCacheRequestWithAuth (Z)V
622620
public final fun setPrivateStorage (Lio/ktor/client/plugins/cache/storage/HttpCacheStorage;)V
623621
public final fun setPublicStorage (Lio/ktor/client/plugins/cache/storage/HttpCacheStorage;)V
624622
public final fun setShared (Z)V

ktor-client/ktor-client-core/api/ktor-client-core.klib.api

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,6 @@ final class io.ktor.client.plugins.cache/HttpCache { // io.ktor.client.plugins.c
333333
final class Config { // io.ktor.client.plugins.cache/HttpCache.Config|null[0]
334334
constructor <init>() // io.ktor.client.plugins.cache/HttpCache.Config.<init>|<init>(){}[0]
335335

336-
final var cacheRequestWithAuth // io.ktor.client.plugins.cache/HttpCache.Config.cacheRequestWithAuth|{}cacheRequestWithAuth[0]
337-
final fun <get-cacheRequestWithAuth>(): kotlin/Boolean // io.ktor.client.plugins.cache/HttpCache.Config.cacheRequestWithAuth.<get-cacheRequestWithAuth>|<get-cacheRequestWithAuth>(){}[0]
338-
final fun <set-cacheRequestWithAuth>(kotlin/Boolean) // io.ktor.client.plugins.cache/HttpCache.Config.cacheRequestWithAuth.<set-cacheRequestWithAuth>|<set-cacheRequestWithAuth>(kotlin.Boolean){}[0]
339336
final var isShared // io.ktor.client.plugins.cache/HttpCache.Config.isShared|{}isShared[0]
340337
final fun <get-isShared>(): kotlin/Boolean // io.ktor.client.plugins.cache/HttpCache.Config.isShared.<get-isShared>|<get-isShared>(){}[0]
341338
final fun <set-isShared>(kotlin/Boolean) // io.ktor.client.plugins.cache/HttpCache.Config.isShared.<set-isShared>|<set-isShared>(kotlin.Boolean){}[0]

ktor-client/ktor-client-core/common/src/io/ktor/client/plugins/cache/HttpCache.kt

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,18 @@ internal val LOGGER = KtorSimpleLogger("io.ktor.client.plugins.HttpCache")
4141
* You can learn more from [Caching](https://ktor.io/docs/client-caching.html).
4242
*/
4343
public class HttpCache private constructor(
44-
@Deprecated("This will become internal", level = DeprecationLevel.ERROR)
45-
@Suppress("DEPRECATION_ERROR")
46-
internal val publicStorage: HttpCacheStorage,
47-
@Deprecated("This will become internal", level = DeprecationLevel.ERROR)
48-
@Suppress("DEPRECATION_ERROR")
49-
internal val privateStorage: HttpCacheStorage,
44+
@Deprecated(
45+
"This will become internal",
46+
level = DeprecationLevel.ERROR
47+
) @Suppress("DEPRECATION_ERROR") internal val publicStorage: HttpCacheStorage,
48+
@Deprecated(
49+
"This will become internal",
50+
level = DeprecationLevel.ERROR
51+
) @Suppress("DEPRECATION_ERROR") internal val privateStorage: HttpCacheStorage,
5052
private val publicStorageNew: CacheStorage,
5153
private val privateStorageNew: CacheStorage,
5254
private val useOldStorage: Boolean,
5355
internal val isSharedClient: Boolean,
54-
internal val cacheRequestWithAuth: Boolean
5556
) {
5657
/**
5758
* A configuration for the [HttpCache] plugin.
@@ -62,17 +63,6 @@ public class HttpCache private constructor(
6263
internal var privateStorageNew: CacheStorage = CacheStorage.Unlimited()
6364
internal var useOldStorage = false
6465

65-
/**
66-
* Specifies if requests with Authorization header should be cached.
67-
*
68-
* According to specification, enabling this flag has security implications.
69-
* See https://datatracker.ietf.org/doc/html/rfc2616#section-14.8,
70-
* https://datatracker.ietf.org/doc/html/rfc7234#section-3,
71-
* and https://datatracker.ietf.org/doc/html/rfc9111#section-3 for the details
72-
*/
73-
@Deprecated("Changing this flag has security implication", level = DeprecationLevel.WARNING)
74-
public var cacheRequestWithAuth: Boolean = false
75-
7666
/**
7767
* Specifies if the client where this plugin is installed is shared among multiple users.
7868
* When set to true, all responses with `private` Cache-Control directive will not be cached.
@@ -143,15 +133,13 @@ public class HttpCache private constructor(
143133
val config = Config().apply(block)
144134

145135
with(config) {
146-
@Suppress("DEPRECATION_ERROR")
147-
return HttpCache(
136+
@Suppress("DEPRECATION_ERROR") return HttpCache(
148137
publicStorage = publicStorage,
149138
privateStorage = privateStorage,
150139
publicStorageNew = publicStorageNew,
151140
privateStorageNew = privateStorageNew,
152141
useOldStorage = useOldStorage,
153-
isSharedClient = isShared,
154-
cacheRequestWithAuth = cacheRequestWithAuth
142+
isSharedClient = isShared
155143
)
156144
}
157145
}
@@ -165,7 +153,7 @@ public class HttpCache private constructor(
165153
if (content !is OutgoingContent.NoContent) return@intercept
166154
if (context.method != HttpMethod.Get || !context.url.protocol.canStore()) return@intercept
167155

168-
if (!plugin.cacheRequestWithAuth && context.headers.contains(HttpHeaders.Authorization)) {
156+
if (plugin.isSharedClient && context.headers.contains(HttpHeaders.Authorization)) {
169157
return@intercept
170158
}
171159

@@ -187,9 +175,8 @@ public class HttpCache private constructor(
187175
val validateStatus = shouldValidate(cache.expires, cache.headers, context)
188176

189177
if (validateStatus == ValidateStatus.ShouldNotValidate) {
190-
val cachedCall = cache
191-
.createResponse(scope, RequestForCache(context.build()), context.executionContext)
192-
.call
178+
val cachedCall =
179+
cache.createResponse(scope, RequestForCache(context.build()), context.executionContext).call
193180
proceedWithCache(scope, cachedCall)
194181
return@intercept
195182
}
@@ -221,17 +208,19 @@ public class HttpCache private constructor(
221208
LOGGER.trace("Caching response for ${response.call.request.url}")
222209
val cachedData = plugin.cacheResponse(response)
223210
if (cachedData != null) {
224-
val reusableResponse = cachedData
225-
.createResponse(scope, response.request, response.coroutineContext)
211+
val reusableResponse =
212+
cachedData.createResponse(scope, response.request, response.coroutineContext)
226213
proceedWith(reusableResponse)
227214
return@intercept
228215
}
229216
}
230217

231218
if (response.status == HttpStatusCode.NotModified) {
232219
LOGGER.trace("Not modified response for ${response.call.request.url}, replying from cache")
233-
val responseFromCache = plugin.findAndRefresh(response.call.request, response)
234-
?: throw InvalidCacheStateException(response.call.request.url)
220+
val responseFromCache =
221+
plugin.findAndRefresh(response.call.request, response) ?: throw InvalidCacheStateException(
222+
response.call.request.url
223+
)
235224

236225
scope.monitor.raise(HttpResponseFromCache, responseFromCache)
237226
proceedWith(responseFromCache)
@@ -340,11 +329,9 @@ public class HttpCache private constructor(
340329

341330
else -> {
342331
val requestHeaders = mergedHeadersLookup(request.content, request.headers::get, request.headers::getAll)
343-
storage.findAll(url)
344-
.sortedByDescending { it.responseTime }
345-
.firstOrNull { cachedResponse ->
346-
cachedResponse.varyKeys.all { (key, value) -> requestHeaders(key) == value }
347-
}
332+
storage.findAll(url).sortedByDescending { it.responseTime }.firstOrNull { cachedResponse ->
333+
cachedResponse.varyKeys.all { (key, value) -> requestHeaders(key) == value }
334+
}
348335
}
349336
}
350337

ktor-client/ktor-client-core/jvm/test/HttpCacheTest.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class HttpCacheTest {
7070
}
7171

7272
@Test
73-
fun `should mix ETags when Authorization header is present and flag enabled`() = testApplication {
73+
fun `should mix ETags when Authorization header is present and client is not shared`() = testApplication {
7474
application {
7575
routing {
7676
get("/me") {
@@ -92,11 +92,7 @@ class HttpCacheTest {
9292
}
9393

9494
val client = createClient {
95-
install(HttpCache) {
96-
isShared = true
97-
@Suppress("DEPRECATION")
98-
cacheRequestWithAuth = true
99-
}
95+
install(HttpCache)
10096
}
10197

10298
assertEquals(

0 commit comments

Comments
 (0)