diff --git a/code/README.md b/code/README.md index 702ed0789d..68c743a36d 100644 --- a/code/README.md +++ b/code/README.md @@ -5,7 +5,7 @@ com.expediagroup rapid-sdk - 5.3.1 + 5.3.2-SNAPSHOT ``` diff --git a/code/pom.xml b/code/pom.xml index 8722edf2a9..3a76123613 100644 --- a/code/pom.xml +++ b/code/pom.xml @@ -4,9 +4,9 @@ 4.0.0 com.expediagroup rapid-sdk - 5.3.1 + 5.3.2-SNAPSHOT EG rapid-sdk for Java - EG rapid-sdk v5.3.1 + EG rapid-sdk v5.3.2-SNAPSHOT https://github.com/ExpediaGroup/test-sdk 2022 jar @@ -74,15 +74,15 @@ 3.6.0 3.4.0 0.8.12 - 1.9.20 + 2.0.0 1.2.1 4.6 1.6.0 - 2.0.21 - 1.9.0 - 2.3.13 - 0.26.1 + 2.1.0 + 1.10.1 + 3.0.3 + 0.27.0 2.0.16 1.7.0 3.2.7 @@ -138,7 +138,7 @@ com.squareup.okio okio-jvm - 3.9.1 + 3.10.2 org.jetbrains @@ -449,6 +449,7 @@ org.jetbrains.dokka dokka-maven-plugin + ${dokka-plugin.version} ${project.basedir}/src/main/kotlin/com/expediagroup/sdk/rapid @@ -732,13 +733,13 @@ org.apache.commons commons-lang3 - 3.14.0 + 3.17.0 org.apache.commons commons-text - 1.12.0 + 1.13.0 diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/client/Client.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/client/Client.kt index de2847b942..d0d57c7ca0 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/client/Client.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/client/Client.kt @@ -54,7 +54,7 @@ import okhttp3.Dispatcher import okhttp3.OkHttpClient // Create a Dispatcher with limits -val dispatcher = +val configuredDispatcher = Dispatcher().apply { maxRequests = 10000 // Maximum number of concurrent requests maxRequestsPerHost = 1000 @@ -64,7 +64,7 @@ val DEFAULT_HTTP_CLIENT_ENGINE: HttpClientEngine = OkHttp.create { config { eventListenerFactory(OkHttpEventListener.FACTORY) - dispatcher(dispatcher) + dispatcher(configuredDispatcher) } } diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/client/ExpediaGroupClient.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/client/ExpediaGroupClient.kt index b47306debb..fc84287e18 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/client/ExpediaGroupClient.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/client/ExpediaGroupClient.kt @@ -67,4 +67,20 @@ abstract class ExpediaGroupClient( return self() } } + + @Suppress("unused", "UnnecessaryAbstractClass") // This is used by the generated SDK clients. + abstract class BuilderWithHttpClient> : Client.BuilderWithHttpClient() { + /** Sets the API auth endpoint to use for requests. */ + protected var authEndpoint: String? = null + + /** Sets the API auth endpoint to use for requests. + * + * @param authEndpoint The API auth endpoint to use for requests. + * @return The [Builder] instance. + */ + fun authEndpoint(authEndpoint: String): SELF { + this.authEndpoint = authEndpoint + return self() + } + } } diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/configuration/provider/XapConfigurationProvider.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/configuration/provider/XapConfigurationProvider.kt index 20857cce79..48cf654dd3 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/configuration/provider/XapConfigurationProvider.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/configuration/provider/XapConfigurationProvider.kt @@ -15,11 +15,6 @@ */ package com.expediagroup.sdk.core.configuration.provider -import com.expediagroup.sdk.core.configuration.provider.RapidConfigurationProvider.connectionTimeout -import com.expediagroup.sdk.core.configuration.provider.RapidConfigurationProvider.endpoint -import com.expediagroup.sdk.core.configuration.provider.RapidConfigurationProvider.name -import com.expediagroup.sdk.core.configuration.provider.RapidConfigurationProvider.requestTimeout -import com.expediagroup.sdk.core.configuration.provider.RapidConfigurationProvider.socketTimeout import com.expediagroup.sdk.core.constant.Constant /** diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/constant/Constant.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/constant/Constant.kt index 5f7a9d8c1d..613ee7bb22 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/constant/Constant.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/constant/Constant.kt @@ -15,13 +15,13 @@ */ package com.expediagroup.sdk.core.constant -import io.ktor.client.plugins.HttpTimeout +import io.ktor.client.plugins.HttpTimeoutConfig internal object Constant { const val EMPTY_STRING = "" const val TEN_SECONDS_IN_MILLIS = 10_000L const val FIFTEEN_SECONDS_IN_MILLIS = 15_000L - const val INFINITE_TIMEOUT = HttpTimeout.INFINITE_TIMEOUT_MS + const val INFINITE_TIMEOUT = HttpTimeoutConfig.INFINITE_TIMEOUT_MS private const val SUCCESSFUL_STATUS_CODES_RANGE_START = 200 private const val SUCCESSFUL_STATUS_CODES_RANGE_END = 299 diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/constant/LoggingMessage.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/constant/LoggingMessage.kt index 50d9b3bce2..ab28716b01 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/constant/LoggingMessage.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/constant/LoggingMessage.kt @@ -29,4 +29,8 @@ internal object LoggingMessage { const val TOKEN_EXPIRED = "Token expired or is about to expire. Request will wait until token is renewed" const val OMITTED = "<-- omitted -->" + + const val LOG_LIMIT = 4094 + + const val TRUNCATED = "<-- truncated -->" } diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/model/paging/Paginator.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/model/paging/Paginator.kt index 7fbaa064b2..6a56e39f5d 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/model/paging/Paginator.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/model/paging/Paginator.kt @@ -24,7 +24,6 @@ import io.ktor.client.statement.HttpResponse sealed class BasePaginator( private val client: Client, firstResponse: Response, - private val fallbackBody: T, private val getBody: suspend (HttpResponse) -> T ) : Iterator { private var state: ResponseState = DefaultResponseState(firstResponse) @@ -41,7 +40,7 @@ sealed class BasePaginator( protected fun nextResponse(): Response { val response = state.getNextResponse() - state = ResponseStateFactory.getState(extractLink(response.headers), client, fallbackBody, getBody) + state = ResponseStateFactory.getState(extractLink(response.headers), client, getBody) return response } } @@ -56,9 +55,8 @@ sealed class BasePaginator( class Paginator( client: Client, firstResponse: Response, - fallbackBody: T, getBody: suspend (HttpResponse) -> T -) : BasePaginator(client, firstResponse, fallbackBody, getBody) { +) : BasePaginator(client, firstResponse, getBody) { /** * Returns the body of the next response. * @@ -77,9 +75,8 @@ class Paginator( class ResponsePaginator( client: Client, firstResponse: Response, - fallbackBody: T, getBody: suspend (HttpResponse) -> T -) : BasePaginator, T>(client, firstResponse, fallbackBody, getBody) { +) : BasePaginator, T>(client, firstResponse, getBody) { /** * Returns the next response. * diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/model/paging/ResponseState.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/model/paging/ResponseState.kt index 19897831d8..69a4177e0b 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/model/paging/ResponseState.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/model/paging/ResponseState.kt @@ -16,17 +16,9 @@ package com.expediagroup.sdk.core.model.paging import com.expediagroup.sdk.core.client.Client -import com.expediagroup.sdk.core.constant.HeaderValue import com.expediagroup.sdk.core.model.Response -import com.expediagroup.sdk.core.plugin.logging.GZipEncoder.decode -import com.expediagroup.sdk.core.plugin.logging.contentEncoding import io.ktor.client.statement.HttpResponse -import io.ktor.util.InternalAPI -import io.ktor.util.moveToByteArray -import io.ktor.utils.io.ByteReadChannel -import io.ktor.utils.io.bits.Memory import kotlinx.coroutines.runBlocking -import java.nio.ByteBuffer internal interface ResponseState { fun getNextResponse(): Response @@ -51,7 +43,6 @@ internal class LastResponseState : ResponseState { internal class FetchLinkState( private val link: String, private val client: Client, - private val fallbackBody: T, private val getBody: suspend (HttpResponse) -> T ) : ResponseState { override fun getNextResponse(): Response = @@ -63,23 +54,7 @@ internal class FetchLinkState( override fun hasNext(): Boolean = true - private suspend fun parseBody(response: HttpResponse): T = if (decodeBody(response).isEmpty()) fallbackBody else getBody(response) - - private suspend fun decodeBody(response: HttpResponse): String { - val byteReadChannel = prepareByteReadChannel(response) - val decodedByteReadChannel = if (response.contentEncoding().equals(HeaderValue.GZIP)) client.httpClient.decode(byteReadChannel) else byteReadChannel - val bodyString: String = decodedByteReadChannel.readRemaining().readText() - return bodyString - } - - @OptIn(InternalAPI::class) - private suspend fun prepareByteReadChannel(response: HttpResponse): ByteReadChannel { - val bufferSize = response.content.availableForRead - val buffer = ByteBuffer.allocate(bufferSize) - val numberOfBytesRead = response.content.peekTo(Memory(buffer), 0, 0, 0, bufferSize.toLong()).toInt() - val byteReadChannel = ByteReadChannel(buffer.moveToByteArray(), 0, numberOfBytesRead) - return byteReadChannel - } + private suspend fun parseBody(response: HttpResponse): T = getBody(response) } internal class ResponseStateFactory { @@ -87,8 +62,7 @@ internal class ResponseStateFactory { fun getState( link: String?, client: Client, - fallbackBody: T, getBody: suspend (HttpResponse) -> T - ): ResponseState = link?.let { FetchLinkState(it, client, fallbackBody, getBody) } ?: LastResponseState() + ): ResponseState = link?.let { FetchLinkState(it, client, getBody) } ?: LastResponseState() } } diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/authentication/strategy/AuthenticationStrategy.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/authentication/strategy/AuthenticationStrategy.kt index 6a44a53d49..ec5e5f5c0d 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/authentication/strategy/AuthenticationStrategy.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/authentication/strategy/AuthenticationStrategy.kt @@ -20,11 +20,11 @@ import com.expediagroup.sdk.core.plugin.authentication.AuthenticationConfigurati import com.expediagroup.sdk.core.plugin.authentication.strategy.AuthenticationStrategy.AuthenticationType.BASIC import com.expediagroup.sdk.core.plugin.authentication.strategy.AuthenticationStrategy.AuthenticationType.BEARER import com.expediagroup.sdk.core.plugin.authentication.strategy.AuthenticationStrategy.AuthenticationType.SIGNATURE -import io.ktor.client.plugins.auth.Auth +import io.ktor.client.plugins.auth.AuthConfig import io.ktor.client.request.HttpRequestBuilder internal interface AuthenticationStrategy { - fun loadAuth(auth: Auth) {} + fun loadAuth(auth: AuthConfig) {} fun isTokenAboutToExpire(): Boolean diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/authentication/strategy/BasicAuthenticationStrategy.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/authentication/strategy/BasicAuthenticationStrategy.kt index 2d87d76dfb..c6e01389db 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/authentication/strategy/BasicAuthenticationStrategy.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/authentication/strategy/BasicAuthenticationStrategy.kt @@ -16,7 +16,7 @@ package com.expediagroup.sdk.core.plugin.authentication.strategy import com.expediagroup.sdk.core.plugin.authentication.AuthenticationConfiguration -import io.ktor.client.plugins.auth.Auth +import io.ktor.client.plugins.auth.AuthConfig import io.ktor.client.plugins.auth.providers.BasicAuthCredentials import io.ktor.client.plugins.auth.providers.basic import io.ktor.client.request.HttpRequestBuilder @@ -24,8 +24,8 @@ import io.ktor.client.request.HttpRequestBuilder internal class BasicAuthenticationStrategy( private val configs: AuthenticationConfiguration ) : AuthenticationStrategy { - override fun loadAuth(auth: Auth) { - auth.basic { + override fun loadAuth(authConfig: AuthConfig) { + authConfig.basic { sendWithoutRequest { true } credentials { BasicAuthCredentials(username = configs.credentials.key, password = configs.credentials.secret) diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/authentication/strategy/ExpediaGroupAuthenticationStrategy.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/authentication/strategy/ExpediaGroupAuthenticationStrategy.kt index 1404a27bc0..33e1f806fb 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/authentication/strategy/ExpediaGroupAuthenticationStrategy.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/authentication/strategy/ExpediaGroupAuthenticationStrategy.kt @@ -28,11 +28,11 @@ import com.expediagroup.sdk.core.plugin.authentication.AuthenticationConfigurati import com.expediagroup.sdk.core.plugin.logging.ExpediaGroupLoggerFactory import io.ktor.client.HttpClient import io.ktor.client.call.body -import io.ktor.client.plugins.auth.Auth +import io.ktor.client.plugins.auth.AuthConfig +import io.ktor.client.plugins.auth.authProviders import io.ktor.client.plugins.auth.providers.BearerAuthProvider import io.ktor.client.plugins.auth.providers.BearerTokens import io.ktor.client.plugins.auth.providers.bearer -import io.ktor.client.plugins.plugin import io.ktor.client.request.HttpRequestBuilder import io.ktor.client.request.basicAuth import io.ktor.client.request.parameter @@ -53,8 +53,8 @@ internal class ExpediaGroupAuthenticationStrategy( private val log = ExpediaGroupLoggerFactory.getLogger(javaClass) private var bearerTokenStorage = BearerTokensInfo.emptyBearerTokenInfo - override fun loadAuth(auth: Auth) { - auth.bearer { + override fun loadAuth(authConfig: AuthConfig) { + authConfig.bearer { sendWithoutRequest { request -> isIdentityRequest(request) } @@ -94,7 +94,7 @@ internal class ExpediaGroupAuthenticationStrategy( private fun clearTokens(client: HttpClient) { log.info(LoggingMessage.TOKEN_CLEARING_IN_PROGRESS) - client.plugin(Auth).providers.filterIsInstance().first().clearToken() + client.authProviders.filterIsInstance().first().clearToken() bearerTokenStorage = BearerTokensInfo.emptyBearerTokenInfo log.info(LoggingMessage.TOKEN_CLEARING_SUCCESSFUL) } diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ExpediaGroupJsonFieldFilter.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ExpediaGroupJsonFieldFilter.kt deleted file mode 100644 index 9a60c277dd..0000000000 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ExpediaGroupJsonFieldFilter.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2022 Expedia, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.expediagroup.sdk.core.plugin.logging - -import com.ebay.ejmask.core.BaseFilter - -internal class ExpediaGroupJsonFieldFilter(maskedFields: Array) : BaseFilter( - ExpediaGroupJsonFieldPatternBuilder::class.java, - *maskedFields -) diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ExpediaGroupJsonFieldPatternBuilder.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ExpediaGroupJsonFieldPatternBuilder.kt deleted file mode 100644 index 63ca9cfdba..0000000000 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ExpediaGroupJsonFieldPatternBuilder.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2022 Expedia, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.expediagroup.sdk.core.plugin.logging - -import com.ebay.ejmask.extenstion.builder.json.JsonFieldPatternBuilder -import com.expediagroup.sdk.core.constant.LoggingMessage.OMITTED - -internal class ExpediaGroupJsonFieldPatternBuilder : JsonFieldPatternBuilder() { - override fun buildReplacement( - visibleCharacters: Int, - vararg fieldNames: String? - ): String = "\"$1$2$OMITTED\"" -} diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ExpediaGroupLogger.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ExpediaGroupLogger.kt index 6390f5c7aa..8826b46011 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ExpediaGroupLogger.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ExpediaGroupLogger.kt @@ -18,11 +18,11 @@ package com.expediagroup.sdk.core.plugin.logging import com.expediagroup.sdk.core.client.Client import com.expediagroup.sdk.core.constant.LogMaskingFields import com.expediagroup.sdk.core.constant.LoggingMessage.LOGGING_PREFIX +import com.expediagroup.sdk.core.constant.LoggingMessage.LOG_LIMIT +import com.expediagroup.sdk.core.constant.LoggingMessage.TRUNCATED import org.slf4j.Logger internal class ExpediaGroupLogger(private val logger: Logger, private val client: Client? = null) : Logger by logger { - private val mask = LogMasker(getMaskedBodyFieldFilters()) - override fun info(msg: String) { if (logger.isInfoEnabled) { logger.info(decorate(msg)) @@ -41,12 +41,9 @@ internal class ExpediaGroupLogger(private val logger: Logger, private val client } } - private fun decorate(msg: String): String = "$LOGGING_PREFIX ${mask(msg)}" + private fun decorate(msg: String): String = "$LOGGING_PREFIX ${mask(truncate(msg), getMaskedBodyFields())}" - private fun getMaskedBodyFields(): Set = client?.getLoggingMaskedFieldsProvider()?.getMaskedBodyFields() ?: LogMaskingFields.DEFAULT_MASKED_BODY_FIELDS + private fun truncate(msg: String): String = if (msg.length > LOG_LIMIT) "${msg.substring(0, LOG_LIMIT)}$TRUNCATED" else msg - private fun getMaskedBodyFieldFilters(): Iterable = - listOf( - ExpediaGroupJsonFieldFilter(getMaskedBodyFields().toTypedArray()) - ) + private fun getMaskedBodyFields(): Set = client?.getLoggingMaskedFieldsProvider()?.getMaskedBodyFields() ?: LogMaskingFields.DEFAULT_MASKED_BODY_FIELDS } diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/LogMasker.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/LogMasker.kt index 36628610f8..b22a6d64f4 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/LogMasker.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/LogMasker.kt @@ -15,18 +15,28 @@ */ package com.expediagroup.sdk.core.plugin.logging -import com.ebay.ejmask.core.BaseFilter -import com.ebay.ejmask.core.EJMask -import com.ebay.ejmask.core.EJMaskInitializer -import com.ebay.ejmask.core.util.LoggerUtil +import com.expediagroup.sdk.core.constant.LogMaskingRegex.NUMBER_FIELD_REGEX +import com.expediagroup.sdk.core.constant.LoggingMessage.OMITTED +import com.expediagroup.sdk.core.constant.provider.LogMaskingRegexProvider.getMaskedFieldsRegex -internal class LogMasker( - filters: Iterable -) : (String) -> String { - init { - LoggerUtil.register { _, _, _ -> /* disable logging */ } - filters.forEach { EJMaskInitializer.addFilter(it) } - } +internal fun mask( + message: String, + maskedBodyFields: Set +): String = masks.fold(message) { acc, mask -> mask.mask(acc, maskedBodyFields) } - override fun invoke(message: String): String = EJMask.mask(message) +internal fun interface Mask { + fun getRegex(maskedBodyFields: Set): Regex + + fun mask( + string: String, + maskedBodyFields: Set + ): String = string.replace(this.getRegex(maskedBodyFields)) { maskSubstring(it.value) } + + fun maskSubstring(string: String) = OMITTED } + +internal val masks: List = + listOf( + Mask(::getMaskedFieldsRegex), + Mask { NUMBER_FIELD_REGEX } + ) diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/LoggingConfiguration.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/LoggingConfiguration.kt index cd34324a95..70787421b8 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/LoggingConfiguration.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/LoggingConfiguration.kt @@ -26,7 +26,7 @@ internal data class LoggingConfiguration( override val httpClientConfiguration: HttpClientConfig, val maskedLoggingHeaders: Set, val maskedLoggingBodyFields: Set, - val level: LogLevel = LogLevel.HEADERS, + val level: LogLevel = LogLevel.ALL, val getLogger: (client: Client) -> Logger = createCustomLogger ) : KtorPluginConfiguration(httpClientConfiguration) { companion object { diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/LoggingPlugin.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/LoggingPlugin.kt index 758a5df725..b27483e324 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/LoggingPlugin.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/LoggingPlugin.kt @@ -41,8 +41,6 @@ internal object LoggingPlugin : Plugin { client.getLoggingMaskedFieldsProvider().getMaskedHeaderFields().contains(header) } } - configurations.httpClientConfiguration.install(RequestBodyLogger) - configurations.httpClientConfiguration.install(ResponseBodyLogger) } } diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/RequestBodyLogger.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/RequestBodyLogger.kt deleted file mode 100644 index 5a077a148e..0000000000 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/RequestBodyLogger.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2022 Expedia, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.expediagroup.sdk.core.plugin.logging - -import com.expediagroup.sdk.core.constant.LoggerName -import com.expediagroup.sdk.core.constant.provider.LoggingMessageProvider -import com.expediagroup.sdk.core.model.getTransactionId -import io.ktor.client.HttpClient -import io.ktor.client.plugins.HttpClientPlugin -import io.ktor.client.request.HttpRequestBuilder -import io.ktor.client.request.HttpSendPipeline -import io.ktor.http.content.OutputStreamContent -import io.ktor.http.contentType -import io.ktor.util.AttributeKey -import io.ktor.util.pipeline.PipelineContext -import io.ktor.utils.io.writer -import kotlinx.coroutines.coroutineScope - -internal class RequestBodyLogger { - private val log = ExpediaGroupLoggerFactory.getLogger(javaClass) - - companion object Plugin : HttpClientPlugin { - override val key: AttributeKey = AttributeKey(LoggerName.REQUEST_BODY_LOGGER) - - override fun install( - plugin: RequestBodyLogger, - scope: HttpClient - ) { - scope.sendPipeline.intercept(HttpSendPipeline.Monitoring) { - val body: String = getBody() - plugin.log.debug(LoggingMessageProvider.getRequestBodyMessage(body, context.headers.getTransactionId())) - proceed() - } - } - - private suspend fun PipelineContext.getBody(): String { - val body = - when { - context.contentType() in LoggableContentTypes -> context.body - else -> return "Body of type ${context.contentType()?.contentType} cannot be logged!" - } - - if (body is OutputStreamContent) { - return coroutineScope { - writer { - body.writeTo(channel) - }.channel.readRemaining().readText() - } - } - return body.toString() - } - - override fun prepare(block: RequestBodyLoggerConfig.() -> Unit): RequestBodyLogger = RequestBodyLogger() - } -} - -internal class RequestBodyLoggerConfig diff --git a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ResponseBodyLogger.kt b/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ResponseBodyLogger.kt deleted file mode 100644 index c06f8fdc7f..0000000000 --- a/code/src/main/kotlin/com/expediagroup/sdk/core/plugin/logging/ResponseBodyLogger.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2022 Expedia, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.expediagroup.sdk.core.plugin.logging - -import com.expediagroup.sdk.core.constant.HeaderValue -import com.expediagroup.sdk.core.constant.LoggerName -import com.expediagroup.sdk.core.constant.provider.LoggingMessageProvider -import com.expediagroup.sdk.core.model.getTransactionId -import com.expediagroup.sdk.core.plugin.logging.GZipEncoder.decode -import io.ktor.client.HttpClient -import io.ktor.client.plugins.HttpClientPlugin -import io.ktor.client.plugins.compression.ContentEncoder -import io.ktor.client.statement.HttpResponse -import io.ktor.client.statement.HttpResponsePipeline -import io.ktor.client.statement.request -import io.ktor.http.HttpHeaders -import io.ktor.http.contentType -import io.ktor.util.AttributeKey -import io.ktor.util.Encoder -import io.ktor.util.GZip -import io.ktor.util.InternalAPI -import io.ktor.utils.io.ByteReadChannel - -class ResponseBodyLogger { - private val log = ExpediaGroupLoggerFactory.getLogger(javaClass) - - companion object Plugin : HttpClientPlugin { - override val key: AttributeKey = AttributeKey(LoggerName.RESPONSE_BODY_LOGGER) - - @OptIn(InternalAPI::class) - override fun install( - plugin: ResponseBodyLogger, - scope: HttpClient - ) { - scope.responsePipeline.intercept(HttpResponsePipeline.Receive) { - val response: HttpResponse = context.response - val byteReadChannel: ByteReadChannel = if (response.contentEncoding().equals(HeaderValue.GZIP)) scope.decode(response.content) else response.content - - when { - response.contentType() in LoggableContentTypes -> - LoggingMessageProvider.getResponseBodyMessage( - byteReadChannel.readRemaining().readText(), - response.request.headers.getTransactionId() - ) - else -> LoggingMessageProvider.getResponseBodyMessage("Body of type ${response.contentType()?.contentType} cannot be logged!", response.request.headers.getTransactionId()) - }.let { - plugin.log.debug(it) - } - - proceed() - } - } - - override fun prepare(block: ResponseBodyLoggerConfig.() -> Unit): ResponseBodyLogger = ResponseBodyLogger() - } -} - -fun HttpResponse.contentEncoding(): String? = headers[HttpHeaders.ContentEncoding] - -internal object GZipEncoder : ContentEncoder, Encoder by GZip { - override val name: String = HeaderValue.GZIP -} - -class ResponseBodyLoggerConfig diff --git a/code/src/main/kotlin/com/expediagroup/sdk/rapid/client/RapidClient.kt b/code/src/main/kotlin/com/expediagroup/sdk/rapid/client/RapidClient.kt index 20de3f7b4e..14471f8727 100644 --- a/code/src/main/kotlin/com/expediagroup/sdk/rapid/client/RapidClient.kt +++ b/code/src/main/kotlin/com/expediagroup/sdk/rapid/client/RapidClient.kt @@ -1697,7 +1697,7 @@ class RapidClient private constructor(clientConfiguration: RapidClientConfigurat @JvmOverloads fun getPaginator(operation: GetInactivePropertiesOperation): ResponsePaginator> { val response = execute(operation) - return ResponsePaginator(this, response, emptyList()) { it.body>() } + return ResponsePaginator(this, response) { it.body>() } } @JvmOverloads @@ -1719,7 +1719,7 @@ class RapidClient private constructor(clientConfiguration: RapidClientConfigurat null ): Paginator> { val response = getInactivePropertiesWithResponse(customerSessionId, since, token, billingTerms, partnerPointOfSale, paymentTerms, platformName) - return Paginator(this, response, emptyList()) { it.body>() } + return Paginator(this, response) { it.body>() } } @JvmOverloads @@ -1741,7 +1741,7 @@ class RapidClient private constructor(clientConfiguration: RapidClientConfigurat null ): ResponsePaginator> { val response = getInactivePropertiesWithResponse(customerSessionId, since, token, billingTerms, partnerPointOfSale, paymentTerms, platformName) - return ResponsePaginator(this, response, emptyList()) { it.body>() } + return ResponsePaginator(this, response) { it.body>() } } /** @@ -2395,7 +2395,7 @@ class RapidClient private constructor(clientConfiguration: RapidClientConfigurat @JvmOverloads fun getPaginator(operation: GetPropertyContentOperation): ResponsePaginator> { val response = execute(operation) - return ResponsePaginator(this, response, emptyMap()) { it.body>() } + return ResponsePaginator(this, response) { it.body>() } } @JvmOverloads @@ -2505,7 +2505,7 @@ class RapidClient private constructor(clientConfiguration: RapidClientConfigurat paymentTerms, platformName ) - return Paginator(this, response, emptyMap()) { it.body>() } + return Paginator(this, response) { it.body>() } } @JvmOverloads @@ -2615,7 +2615,7 @@ class RapidClient private constructor(clientConfiguration: RapidClientConfigurat paymentTerms, platformName ) - return ResponsePaginator(this, response, emptyMap()) { it.body>() } + return ResponsePaginator(this, response) { it.body>() } } /** @@ -3301,7 +3301,7 @@ class RapidClient private constructor(clientConfiguration: RapidClientConfigurat @JvmOverloads fun getPaginator(operation: GetRegionsOperation): ResponsePaginator> { val response = execute(operation) - return ResponsePaginator(this, response, emptyList()) { it.body>() } + return ResponsePaginator(this, response) { it.body>() } } @JvmOverloads @@ -3362,7 +3362,7 @@ class RapidClient private constructor(clientConfiguration: RapidClientConfigurat paymentTerms, platformName ) - return Paginator(this, response, emptyList()) { it.body>() } + return Paginator(this, response) { it.body>() } } @JvmOverloads @@ -3423,7 +3423,7 @@ class RapidClient private constructor(clientConfiguration: RapidClientConfigurat paymentTerms, platformName ) - return ResponsePaginator(this, response, emptyList()) { it.body>() } + return ResponsePaginator(this, response) { it.body>() } } /**