Repository: ktorio/ktor
File: ktor-client/ktor-client-core/common/src/io/ktor/client/engine/HttpClientEngine.kt (Kotlin)

Code before:
            response.coroutineContext.job.invokeOnCompletion {
                if (it != null) {
                    client.monitor.raise(HttpResponseCancelled, response)
                }
            }

            proceedWith(call)
        }
    }

    /**
     * Creates a call context and uses it as a coroutine context to [execute] a request.
     */
    @OptIn(InternalAPI::class)
    private suspend fun executeWithinCallContext(requestData: HttpRequestData): HttpResponseData {
        val callContext = createCallContext(requestData.executionContext)

        return withContext(callContext + KtorCallContextElement(callContext)) {
            if (closed) {
                throw ClientEngineClosedException()
            }

            execute(requestData)
        }
    }

    private fun checkExtensions(requestData: HttpRequestData) {
        for (requestedExtension in requestData.requiredCapabilities) {
            require(supportedCapabilities.contains(requestedExtension)) { "Engine doesn't support $requestedExtension" }
        }
    }
}

/**
 * A factory of [HttpClientEngine] with a specific [T] of [HttpClientEngineConfig].
 */
public interface HttpClientEngineFactory<out T : HttpClientEngineConfig> {
    /**
     * Creates a new [HttpClientEngine] optionally specifying a [block] configuring [T].
     */
    public fun create(block: T.() -> Unit = {}): HttpClientEngine
}

/**
 * Creates a new [HttpClientEngineFactory] based on this one
 * with further configurations from the [nested] block.
 */
public fun <T : HttpClientEngineConfig> HttpClientEngineFactory<T>.config(
    nested: T.() -> Unit
): HttpClientEngineFactory<T> {
    val parent = this

Review comment (suggestion):
Unrelated change. Replaced `async { ... }.await()` with `withContext`

Code after:
            response.coroutineContext.job.invokeOnCompletion {
                if (it != null) {
                    client.monitor.raise(HttpResponseCancelled, response)
                }
            }

            proceedWith(call)
        }
    }

    /**
     * Creates a call context and uses it as a coroutine context to [execute] a request.
     */
    @OptIn(InternalAPI::class)
    private suspend fun executeWithinCallContext(requestData: HttpRequestData): HttpResponseData {
        val callContext = createCallContext(requestData.executionContext)

        val context = callContext + KtorCallContextElement(callContext)
        return async(context) {
            if (closed) {
                throw ClientEngineClosedException()
            }

            execute(requestData)
        }.await()
    }

    private fun checkExtensions(requestData: HttpRequestData) {
        for (requestedExtension in requestData.requiredCapabilities) {
            require(supportedCapabilities.contains(requestedExtension)) { "Engine doesn't support $requestedExtension" }
        }
    }
}

/**
 * A factory of [HttpClientEngine] with a specific [T] of [HttpClientEngineConfig].
 */
public interface HttpClientEngineFactory<out T : HttpClientEngineConfig> {
    /**
     * Creates a new [HttpClientEngine] optionally specifying a [block] configuring [T].
     */
    public fun create(block: T.() -> Unit = {}): HttpClientEngine
}

/**
 * Creates a new [HttpClientEngineFactory] based on this one
 * with further configurations from the [nested] block.
 */
public fun <T : HttpClientEngineConfig> HttpClientEngineFactory<T>.config(
    nested: T.() -> Unit
): HttpClientEngineFactory<T> {