Repository: ktorio/ktor
File: ktor-client/ktor-client-core/common/src/io/ktor/client/plugins/observer/DelegatedCall.kt (Kotlin)

Code before:
 *
 * **Warning:** The content of the returned call response is non-replayable, so it can be consumed only once.
 * Consider using `wrapWithContent` with lambda instead.
 *
 * [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.client.plugins.observer.wrap)
 */
@Deprecated("Use 'wrap' with lambda instead.", ReplaceWith("wrap(headers) { content }"))
public fun HttpClientCall.wrap(content: ByteReadChannel, headers: Headers): HttpClientCall {
    return DelegatedCall(client, content, this, headers)
}

/**
 * Wrap existing [HttpClientCall] with new [headers] and content produced by the given [block].
 * The [block] will be called each time the response content is requested.
 *
 * ```
 * // Example: Content decompression. See ContentEncoding implementation for full example
 * val originalContent = originalCall.response.content
 * val decodedCall = originalCall.wrap(headersOf("Content-Encoding", "identity")) {
 *     decodeGzip(originalContent) // returns a new ByteReadChannel with decoded content
 * }
 * ```
 *
 * [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.client.plugins.observer.wrap)
 */
public fun HttpClientCall.wrap(headers: Headers, block: () -> ByteReadChannel): HttpClientCall {
    return DelegatedCall(client, block, this, headers)
}

internal class DelegatedCall(
    client: HttpClient,
    block: () -> ByteReadChannel,
    originCall: HttpClientCall,
    responseHeaders: Headers = originCall.response.headers
) : HttpClientCall(client) {

    constructor(
        client: HttpClient,
        content: ByteReadChannel,
        originCall: HttpClientCall,
        responseHeaders: Headers = originCall.response.headers
    ) : this(client, { content }, originCall, responseHeaders)

    init {
        request = DelegatedRequest(this, originCall.request)
        response = DelegatedResponse(this, block, originCall.response, responseHeaders)
    }
}

internal class DelegatedRequest(
    override val call: HttpClientCall,

Review comment (suggestion):
To be discussed. Should we pass current `rawContent` as a parameter to the `block`?
We could rename `wrap` into `transform` (or `transformContent`) and then it would be logical to have such a parameter.

Code after:
/*
 * Copyright 2014-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
 */

package io.ktor.client.plugins.observer

import io.ktor.client.call.*
import io.ktor.http.*
import io.ktor.utils.io.*

/**
 * Wrap existing [HttpClientCall] with new [content].
 *
 * **Warning:** The content of the returned call response is non-replayable, so it can be consumed only once.
 * Consider using `replaceResponse` instead.
 *
 * [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.client.plugins.observer.wrapWithContent)
 */
@Deprecated(
    "Use 'replaceResponse' instead.",
    ReplaceWith(
        "replaceResponse { content }",
        "io.ktor.client.call.replaceResponse"
    )
)
public fun HttpClientCall.wrapWithContent(content: ByteReadChannel): HttpClientCall = replaceResponse { content }

/**
 * Wrap existing [HttpClientCall] with new content produced by the given [block].
 * The [block] will be called each time the response content is requested.
 *
 * [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.client.plugins.observer.wrapWithContent)
 */
@Deprecated(
    "Use 'replaceResponse' instead.",
    ReplaceWith(
        "replaceResponse { block() }",
        "io.ktor.client.call.replaceResponse"
    )
)
public fun HttpClientCall.wrapWithContent(block: () -> ByteReadChannel): HttpClientCall = replaceResponse { block() }

/**
 * Wrap existing [HttpClientCall] with new response [content] and [headers].
 *
 * **Warning:** The content of the returned call response is non-replayable, so it can be consumed only once.
 * Consider using `replaceResponse` instead.
 *
 * [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.client.plugins.observer.wrap)
 */
@Deprecated(
    "Use 'replaceResponse' instead.",
    ReplaceWith(
        "replaceResponse(headers) { content }",
        "io.ktor.client.call.replaceResponse"
    )
)
public fun HttpClientCall.wrap(content: ByteReadChannel, headers: Headers): HttpClientCall =
    replaceResponse(headers) { content }