xyz.shoaky.sourcedownloader.sdk.api.ApiClient.kt Maven / Gradle / Ivy
The newest version!
package xyz.shoaky.sourcedownloader.sdk.api
import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
import com.google.common.net.HttpHeaders
import com.google.common.net.MediaType
import org.slf4j.LoggerFactory
import org.springframework.web.util.UriComponentsBuilder
import xyz.shoaky.sourcedownloader.sdk.api.BaseRequest.Companion.stringTypeReference
import xyz.shoaky.sourcedownloader.sdk.util.Http
import xyz.shoaky.sourcedownloader.sdk.util.Jackson
import java.net.CookieManager
import java.net.URI
import java.net.URLEncoder
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
interface ApiClient {
fun , T : Any> execute(endpoint: URI, request: R): HttpResponse
}
abstract class HookedApiClient : ApiClient {
override fun , T : Any> execute(endpoint: URI, request: R): HttpResponse {
val uriBuilder = UriComponentsBuilder.fromUri(endpoint).path(request.path)
if (request.httpMethod === HttpMethod.GET) {
Jackson.convertToMap(request)
.forEach {
uriBuilder.queryParam(it.key, it.value)
}
} else {
request.queryString.forEach { (k, v) ->
uriBuilder.queryParam(k, v)
}
}
val requestBuilder = HttpRequest.newBuilder(uriBuilder.build().toUri())
.method(request.httpMethod.name, bodyPublisher(request))
request.setHeader(HttpHeaders.CONTENT_TYPE, request.mediaType)
request.httpHeaders().forEach { (name, value) -> requestBuilder.header(name, value) }
beforeRequest(requestBuilder, request)
val httpRequest = requestBuilder.build()
val httpResponse = httpClient.send(httpRequest, bodyHandler(request))
if (log.isDebugEnabled) {
log.debug(
"""
request:{}
requestBody:{}
responseCode:{}
responseBody:{}
""", httpRequest.uri(), Jackson.toJsonString(httpRequest),
httpResponse.statusCode(), httpResponse.body())
}
afterRequest(httpResponse, request)
return httpResponse as HttpResponse
}
abstract fun , T : Any> beforeRequest(requestBuilder: HttpRequest.Builder, request: R)
abstract fun , T : Any> afterRequest(response: HttpResponse, request: R)
private fun , T : Any> bodyHandler(request: BaseRequest): HttpResponse.BodyHandler {
if (request.mediaType == MediaType.JSON_UTF_8) {
return Http.JsonBodyHandler(request.responseBodyType)
}
if (request.responseBodyType == stringTypeReference) {
@Suppress("UNCHECKED_CAST")
return stringBodyHandler as HttpResponse.BodyHandler
}
return Http.JsonBodyHandler(request.responseBodyType)
}
private fun , T : Any> bodyPublisher(request: BaseRequest): HttpRequest.BodyPublisher {
val mediaType = request.mediaType
if (mediaType == MediaType.FORM_DATA || mediaType == MediaType.PLAIN_TEXT_UTF_8) {
val data = Jackson.convert(request, jacksonTypeRef