This is a pull request to enable dynamic http request, see issue mentioned here: https://github.com/rybalkinsd/kohttp/issues/169
Summary:
With the current version the end-user needs to explicitly specify which http context to use for each http method type, see here code snippet from the issue https://github.com/rybalkinsd/kohttp/issues/169:
package it.skrape.core.fetcher
import io.github.rybalkinsd.kohttp.client.defaultHttpClient
import io.github.rybalkinsd.kohttp.client.fork
import io.github.rybalkinsd.kohttp.dsl.*
import io.github.rybalkinsd.kohttp.dsl.context.HttpContext
import io.github.rybalkinsd.kohttp.ext.url
import it.skrape.core.Request
import it.skrape.core.Result
import org.jsoup.Connection
class KoFetcher(private val request: Request): Fetcher {
private val client = defaultHttpClient.fork {
followRedirects = request.followRedirects
readTimeout = request.timeout.toLong()
}
override fun fetch(): Result {
val requester = when(request.method) {
Connection.Method.GET -> httpGet(client, getContext())
Connection.Method.POST -> httpPost(client, getContext())
Connection.Method.PUT -> httpPut(client, getContext())
Connection.Method.DELETE -> httpDelete(client, getContext())
Connection.Method.PATCH -> httpPatch(client, getContext())
Connection.Method.HEAD -> httpHead(client, getContext())
else -> throw UnsupportedOperationException("Method is not supported by KoHttp")
}
requester.use {
return Result(
responseBody = it.body()?.string() ?: "",
statusCode = it.code(),
statusMessage = it.message(),
contentType = it.header("Content-Type"),
headers = it.headers().names().associateBy({item -> item}, {item -> it.header(item, "")!!}),
request = request
)
}
}
private fun getContext(): HttpContext.() -> Unit = {
url(request.url)
header {
request.headers
"User-Agent" to request.userAgent
cookie {
request.cookies
}
}
}
}
Provided solution
Within this pull request a http request can be executed by either specifying the http method or http context. The underlying function will determine during runtime which http context to use by the provided arguments.
The above snippet can be rewritten with the following snippet:
package it.skrape.core.fetcher
import io.github.rybalkinsd.kohttp.client.defaultHttpClient
import io.github.rybalkinsd.kohttp.client.fork
import io.github.rybalkinsd.kohttp.dsl.*
import io.github.rybalkinsd.kohttp.dsl.context.HttpContext
import io.github.rybalkinsd.kohttp.ext.url
import it.skrape.core.Request
import it.skrape.core.Result
import org.jsoup.Connection
class KoFetcher(private val request: Request): Fetcher {
private val client = defaultHttpClient.fork {
followRedirects = request.followRedirects
readTimeout = request.timeout.toLong()
}
override fun fetch(): Result {
method: Method = Method.valueOf(request.method.toString)
val requester = http(method = method, init = getContext)
requester.use {
return Result(
responseBody = it.body()?.string() ?: "",
statusCode = it.code(),
statusMessage = it.message(),
contentType = it.header("Content-Type"),
headers = it.headers().names().associateBy({item -> item}, {item -> it.header(item, "")!!}),
request = request
)
}
}
private fun getContext(): HttpContext.() -> Unit = {
url(request.url)
header {
request.headers
"User-Agent" to request.userAgent
cookie {
request.cookies
}
}
}
}
Note
This pull request is currently WIP to get review input on the initial solution. Some unit tests are already added to provide example usages.
enhancement