Search code examples
kotlinktorktor-client

"None of the following functions can be called with the arguments supplied." on a Ktor request function while using Skrapeit's custom fetcher


Source: Implement your own - skrape{it}

Getting:

None of the following functions can be called with the arguments supplied.

  • HttpClient.request(HttpRequestBuilder = ...) defined in io.ktor.client.request
  • HttpClient.request(HttpRequestBuilder.() → Unit) defined in io.ktor.client.request
  • HttpClient.request(Url, HttpRequestBuilder.() → Unit = ...) defined in io.ktor.client.request
  • HttpClient.request(URL, HttpRequestBuilder.() → Unit = ...) defined in io.ktor.client.request
  • HttpClient.request(String, HttpRequestBuilder.() → Unit = ...) defined in io.ktor.client.request

despite it seems to find the first function: Screenshot

import androidx.compose.foundation.layout.*
import it.skrape.fetcher.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.client.*
import io.ktor.client.engine.android.*
import io.ktor.client.engine.apache.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.*
import io.ktor.client.utils.EmptyContent.headers
import io.ktor.http.*
import io.ktor.http.cio.*
import io.ktor.util.*
import it.skrape.fetcher.Cookie
import kotlinx.coroutines.runBlocking

class KtorBlockingFetcher(val ktorClient: HttpClient) : BlockingFetcher<HttpRequestBuilder> {

    override fun fetch(request: HttpRequestBuilder): Result =
        runBlocking { // runBlocking because ktor is fully build on coroutines but in our example we want it blocking
            with(ktorClient.request<HttpResponse>(request)) { // do http call with ktor client
                Result( // map ktor result to skrape{it} result
                    responseBody = readText(),
                    responseStatus = Result.Status(status.value, status.description),
                    contentType = contentType()?.toString(),
                    headers = headers.toMap().mapValues { it.value.firstOrNull().orEmpty() },
                    baseUri = request.url.toString(),
                    cookies = listOf(setCookie()) as List<Cookie>
                )
            }
        }

    override val requestBuilder: HttpRequestBuilder
        get() = HttpRequestBuilder()
}

val KTOR_CLIENT = HttpClient(Apache)
val result = skrape(KtorBlockingFetcher(KTOR_CLIENT)) {
    request {
        url { Url("https://google.com") }
    }

    response {
        // do your stuff here
    }
}

Unable to understand the problem


Solution

  • The problem is your code for Ktor 1.*, but you has included dependencies of Ktor 2.*. Here is the corrected code:

    fun fetch(request: HttpRequestBuilder): Result = runBlocking { // runBlocking because ktor is fully build on coroutines but in our example we want it blocking
        with(ktorClient.request(request)) { // do http call with ktor client
            Result( // map ktor result to skrape{it} result
                responseBody = bodyAsText(),
                responseStatus = Result.Status(status.value, status.description),
                contentType = contentType()?.toString(),
                headers = headers.toMap().mapValues { it.value.firstOrNull().orEmpty() },
                baseUri = request.url.toString(),
                cookies = listOf(setCookie()) as List<Cookie>
            )
        }
    }