Add basic components for push-message-provider-hpk module
This commit is contained in:
parent
53a2bb680c
commit
3d67f4a1ce
|
|
@ -0,0 +1,3 @@
|
|||
package ru.touchin.push.message.provider.hpk.base.builders
|
||||
|
||||
internal interface Buildable
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package ru.touchin.push.message.provider.hpk.base.clients
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import org.springframework.web.reactive.function.client.ClientResponse
|
||||
import ru.touchin.push.message.provider.hpk.base.clients.dto.ConditionalResponse
|
||||
|
||||
internal open class ConditionalWebClientParser(
|
||||
private val objectMapper: ObjectMapper,
|
||||
) {
|
||||
|
||||
open fun isOkResponse(clientResponse: ClientResponse): Boolean {
|
||||
return clientResponse.statusCode().is2xxSuccessful
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
inline fun <reified S, reified F> parse(
|
||||
clientResponse: ClientResponse,
|
||||
body: String,
|
||||
): ConditionalResponse<S, F> {
|
||||
return if (isOkResponse(clientResponse)) {
|
||||
ConditionalResponse<S, F>(
|
||||
success = parseValue(body, S::class.java),
|
||||
failure = null
|
||||
)
|
||||
} else {
|
||||
ConditionalResponse(
|
||||
success = null,
|
||||
failure = parseValue(body, F::class.java)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> parseValue(source: String?, clazz: Class<T>): T {
|
||||
return if (clazz.canonicalName != String::class.java.canonicalName) {
|
||||
objectMapper.readValue(source, clazz)
|
||||
} else {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
source as T // T is String
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package ru.touchin.push.message.provider.hpk.base.clients
|
||||
|
||||
import io.netty.channel.ChannelOption
|
||||
import io.netty.handler.ssl.SslContextBuilder
|
||||
import io.netty.handler.timeout.ReadTimeoutHandler
|
||||
import io.netty.handler.timeout.WriteTimeoutHandler
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector
|
||||
import org.springframework.web.reactive.function.client.ClientResponse
|
||||
import org.springframework.web.reactive.function.client.WebClient
|
||||
import reactor.core.publisher.Mono
|
||||
import reactor.core.scheduler.Schedulers
|
||||
import reactor.netty.http.client.HttpClient
|
||||
import ru.touchin.common.spring.web.webclient.BaseLogWebClient
|
||||
import ru.touchin.common.spring.web.webclient.dto.RequestLogData
|
||||
import ru.touchin.common.spring.web.webclient.logger.WebClientLogger
|
||||
import ru.touchin.push.message.provider.hpk.base.clients.dto.ConditionalResponse
|
||||
import ru.touchin.push.message.provider.hpk.properties.HpkProperties
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
abstract class ConfigurableWebClient(
|
||||
webClientLogger: WebClientLogger,
|
||||
webClientBuilder: WebClient.Builder,
|
||||
protected val webService: HpkProperties.WebService,
|
||||
) : BaseLogWebClient(webClientLogger, webClientBuilder) {
|
||||
|
||||
private val conditionalWebClientParser: Lazy<ConditionalWebClientParser> = lazy {
|
||||
ConditionalWebClientParser(
|
||||
objectMapper = getObjectMapper(),
|
||||
)
|
||||
}
|
||||
|
||||
protected fun WebClient.Builder.setTimeouts(): WebClient.Builder {
|
||||
val httpClient: HttpClient = HttpClient.create()
|
||||
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, webService.http.connectionTimeout.toMillis().toInt())
|
||||
.doOnConnected { setup ->
|
||||
setup.addHandlerLast(ReadTimeoutHandler(webService.http.readTimeout.toMillis(), TimeUnit.MILLISECONDS))
|
||||
setup.addHandlerLast(WriteTimeoutHandler(webService.http.writeTimeout.toMillis(), TimeUnit.MILLISECONDS))
|
||||
}
|
||||
.let { httpClient ->
|
||||
webService.ssl?.let { ssl ->
|
||||
httpClient.secure { builder ->
|
||||
builder
|
||||
.sslContext(SslContextBuilder.forClient().build())
|
||||
.handshakeTimeout(ssl.handshakeTimeout)
|
||||
.closeNotifyFlushTimeout(ssl.notifyFlushTimeout)
|
||||
.closeNotifyReadTimeout(ssl.notifyReadTimeout)
|
||||
}
|
||||
} ?: httpClient
|
||||
}
|
||||
|
||||
return clientConnector(ReactorClientHttpConnector(httpClient))
|
||||
}
|
||||
|
||||
internal inline fun <reified S, reified F> WebClient.RequestHeadersSpec<*>.exchangeWithWrap(
|
||||
requestLogData: RequestLogData,
|
||||
): Mono<ConditionalResponse<S, F>> {
|
||||
return exchangeToMono { clientResponse ->
|
||||
parse<S, F>(clientResponse)
|
||||
}.doOnNext { responseWrapper ->
|
||||
getLogger().log(
|
||||
requestLogData.copy(
|
||||
responseBody = responseWrapper.success ?: responseWrapper.failure
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun <reified S, reified F> parse(
|
||||
clientResponse: ClientResponse,
|
||||
): Mono<ConditionalResponse<S, F>> {
|
||||
val responseBody = clientResponse
|
||||
.bodyToMono(String::class.java)
|
||||
.defaultIfEmpty(String())
|
||||
.publishOn(Schedulers.parallel())
|
||||
|
||||
return responseBody
|
||||
.map { body ->
|
||||
conditionalWebClientParser.value.parse(
|
||||
clientResponse = clientResponse,
|
||||
body = body,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package ru.touchin.push.message.provider.hpk.base.clients.dto
|
||||
|
||||
internal open class ConditionalResponse<S, F>(
|
||||
val success: S?,
|
||||
val failure: F?,
|
||||
) {
|
||||
|
||||
init {
|
||||
// Only one value should be present
|
||||
check((success == null) != (failure == null))
|
||||
}
|
||||
|
||||
val isSuccess: Boolean = success != null
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package ru.touchin.push.message.provider.hpk.base.enums
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue
|
||||
|
||||
internal interface ValueableSerializableEnum<T> {
|
||||
|
||||
val value: T
|
||||
|
||||
@JsonValue
|
||||
fun toValue(): T = value
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package ru.touchin.push.message.provider.hpk.base.extensions
|
||||
|
||||
import ru.touchin.push.message.provider.hpk.base.builders.Buildable
|
||||
|
||||
fun <V, B : Buildable> B.ifNotNull(value: V?, setter: B.(V) -> B): B {
|
||||
return value?.let { setter(it) } ?: this
|
||||
}
|
||||
Loading…
Reference in New Issue