Skip to content

Commit

Permalink
Merge branch 'main' into OmarAlJarrah/sdk-rest-core-bridging-utils
Browse files Browse the repository at this point in the history
  • Loading branch information
OmarAlJarrah authored Jan 30, 2025
2 parents 8dd1a3c + 8bbe5aa commit 3feedf8
Show file tree
Hide file tree
Showing 18 changed files with 315 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,61 +40,52 @@ abstract class AbstractBearerAuthenticationManager(
*
* @return `true` if the token is near expiration, `false` otherwise.
*/
fun isTokenAboutToExpire(): Boolean =
run {
bearerTokenStorage.isAboutToExpire()
}
fun isTokenAboutToExpire(): Boolean = bearerTokenStorage.isAboutToExpire()

/**
* Clears the stored authentication token.
*
* This method resets the internal token storage, effectively invalidating the current session.
*/
override fun clearAuthentication() =
run {
bearerTokenStorage = BearerTokenStorage.empty
}
override fun clearAuthentication() {
bearerTokenStorage = BearerTokenStorage.empty
}

/**
* Retrieves the stored token formatted as an `Authorization` header value.
*
* @return The token in the format `Bearer <token>` for use in HTTP headers.
*/
fun getAuthorizationHeaderValue(): String =
run {
bearerTokenStorage.getAuthorizationHeaderValue()
}
fun getAuthorizationHeaderValue(): String = bearerTokenStorage.getAuthorizationHeaderValue()

/**
* Creates an HTTP request to fetch a new bearer token from the authentication server.
*
* @return A [Request] object configured with the necessary headers and parameters.
*/
fun buildAuthenticationRequest(): Request =
run {
Request
.Builder()
.url(authUrl)
.method(Method.POST)
.body(
RequestBody
.create(mapOf("grant_type" to "client_credentials")),
).setHeader("Authorization", credentials.encodeBasic())
.setHeader("Content-Type", CommonMediaTypes.APPLICATION_FORM_URLENCODED.toString())
.build()
}
fun buildAuthenticationRequest(): Request {
val body = RequestBody.create(mapOf("grant_type" to "client_credentials"))

return Request
.builder()
.url(authUrl)
.method(Method.POST)
.body(body)
.setHeader("Authorization", credentials.encodeBasic())
.setHeader("Content-Type", CommonMediaTypes.APPLICATION_FORM_URLENCODED.toString())
.build()
}

/**
* Stores the retrieved token in internal storage for subsequent use.
*
* @param bearerTokenResponse The [BearerTokenResponse] containing the token and its expiration time.
*/
fun storeToken(bearerTokenResponse: BearerTokenResponse) =
run {
bearerTokenStorage =
BearerTokenStorage.create(
accessToken = bearerTokenResponse.accessToken,
expiresIn = bearerTokenResponse.expiresIn,
)
}
fun storeToken(bearerTokenResponse: BearerTokenResponse) {
bearerTokenStorage =
BearerTokenStorage.create(
accessToken = bearerTokenResponse.accessToken,
expiresIn = bearerTokenResponse.expiresIn,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,9 @@ class BearerAuthenticationManager(
* @throws ExpediaGroupAuthException If the server responds with an error.
*/
private fun executeAuthenticationRequest(request: Request): Response =
run {
requestExecutor.execute(request).apply {
if (!this.isSuccessful) {
throw throw ExpediaGroupAuthException("Received unsuccessful authentication response: [${this.status}]")
}
requestExecutor.execute(request).apply {
if (!this.isSuccessful) {
throw throw ExpediaGroupAuthException("Received unsuccessful authentication response: [${this.status}]")
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2024 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.exception.client

/**
* Exception class to handle or wrap exceptions thrown by the ExecutionPipeline
*/
class ExpediaGroupPipelineExecutionException(
message: String? = null,
cause: Throwable? = null,
) : ExpediaGroupClientException(message, cause)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2024 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.exception.client

/**
* Exception class to handle or wrap exceptions thrown by the underlying Transport implementation
*/
class ExpediaGroupTransportException(
message: String? = null,
cause: Throwable? = null,
) : ExpediaGroupClientException(message, cause)
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ data class Headers private constructor(
*
* @param name the header name (case-insensitive)
* @return the first header value, or null if not found
* @throws IllegalArgumentException if [name] is null
*/
fun get(name: String): String? = headersMap[sanitizeName(name)]?.firstOrNull()

Expand All @@ -39,7 +38,6 @@ data class Headers private constructor(
*
* @param name the header name (case-insensitive)
* @return an unmodifiable list of header values, or an empty list if none
* @throws IllegalArgumentException if [name] is null
*/
fun values(name: String): List<String> = headersMap[sanitizeName(name)] ?: emptyList()

Expand Down Expand Up @@ -95,7 +93,6 @@ data class Headers private constructor(
* @param name the header name
* @param value the header value
* @return this builder
* @throws IllegalArgumentException if [name] or [value] is invalid
*/
fun add(
name: String,
Expand All @@ -108,7 +105,6 @@ data class Headers private constructor(
* @param name the header name
* @param values the list of header values
* @return this builder
* @throws IllegalArgumentException if [name] or any [values] are invalid
*/
fun add(
name: String,
Expand All @@ -125,7 +121,6 @@ data class Headers private constructor(
* @param name the header name
* @param value the header value
* @return this builder
* @throws IllegalArgumentException if [name] or [value] is invalid
*/
fun set(
name: String,
Expand All @@ -139,7 +134,6 @@ data class Headers private constructor(
* @param name the header name
* @param values the header value
* @return this builder
* @throws IllegalArgumentException if [name] or [values] are invalid
*/
fun set(
name: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ data class Request private constructor(
* @param name The header name.
* @param value The header value.
* @return This builder.
* @throws IllegalArgumentException If [name] or [value] is invalid.
*/
fun addHeader(
name: String,
Expand All @@ -132,7 +131,6 @@ data class Request private constructor(
* @param name The header name.
* @param values The header values list.
* @return This builder.
* @throws IllegalArgumentException If [name] or [values] are invalid.
*/
fun addHeader(
name: String,
Expand All @@ -147,7 +145,6 @@ data class Request private constructor(
* @param name The header name.
* @param value The header value.
* @return This builder.
* @throws IllegalArgumentException If [name] or [value] is invalid.
*/
fun setHeader(
name: String,
Expand All @@ -162,7 +159,6 @@ data class Request private constructor(
* @param name The header name.
* @param values The header values list.
* @return This builder.
* @throws IllegalArgumentException If [name] or [values] are invalid.
*/
fun setHeader(
name: String,
Expand All @@ -187,7 +183,6 @@ data class Request private constructor(
*
* @param name The header name.
* @return This builder.
* @throws IllegalArgumentException If [name] is null.
*/
fun removeHeader(name: String) =
apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ abstract class RequestBody {
* @param formData The form data as a map of parameter names and values.
* @param charset The character set to use; defaults to UTF-8.
* @return A new [RequestBody] instance.
* @throws IllegalArgumentException If [formData] is null.
*/
@JvmStatic
@JvmOverloads
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ data class Response private constructor(
*
* @param status The HTTP status code.
* @return This builder.
* @throws IllegalArgumentException If [status] is negative.
*/
fun status(status: Status) =
apply {
Expand All @@ -139,7 +138,6 @@ data class Response private constructor(
* @param name The header name.
* @param value The header value.
* @return This builder.
* @throws IllegalArgumentException If [name] or [value] is invalid.
*/
fun addHeader(
name: String,
Expand All @@ -154,7 +152,6 @@ data class Response private constructor(
* @param name The header name.
* @param values The header value.
* @return This builder.
* @throws IllegalArgumentException If [name] or [values] are invalid.
*/
fun addHeader(
name: String,
Expand All @@ -169,7 +166,6 @@ data class Response private constructor(
* @param name The header name.
* @param value The header value.
* @return This builder.
* @throws IllegalArgumentException If [name] or [value] is invalid.
*/
fun setHeader(
name: String,
Expand All @@ -184,7 +180,6 @@ data class Response private constructor(
* @param name The header name.
* @param values The header values list.
* @return This builder.
* @throws IllegalArgumentException If [name] or [values] are invalid.
*/
fun setHeader(
name: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import com.expediagroup.sdk.core.authentication.bearer.AbstractBearerAuthenticat
import com.expediagroup.sdk.core.exception.service.ExpediaGroupAuthException
import com.expediagroup.sdk.core.http.Request
import com.expediagroup.sdk.core.pipeline.RequestPipelineStep
import java.io.IOException

class BearerAuthenticationStep(
private val authenticationManager: AbstractBearerAuthenticationManager,
Expand All @@ -41,7 +40,7 @@ class BearerAuthenticationStep(
}
}
}
} catch (e: IOException) {
} catch (e: Exception) {
throw ExpediaGroupAuthException("Failed to authenticate", e)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package com.expediagroup.sdk.core.transport

import com.expediagroup.sdk.core.common.getOrThrow
import com.expediagroup.sdk.core.exception.client.ExpediaGroupConfigurationException
import com.expediagroup.sdk.core.exception.client.ExpediaGroupPipelineExecutionException
import com.expediagroup.sdk.core.exception.client.ExpediaGroupTransportException
import com.expediagroup.sdk.core.http.Request
import com.expediagroup.sdk.core.http.Response
import com.expediagroup.sdk.core.pipeline.ExecutionPipeline
Expand Down Expand Up @@ -75,21 +77,37 @@ abstract class AbstractAsyncRequestExecutor(
*
* @param request The request to be processed through the pipelines.
* @return [CompletableFuture] attached with a callback for response pipeline execution
* @throws ExpediaGroupPipelineExecutionException if the request pipelines fails
*/
fun execute(request: Request): CompletableFuture<Response> =
executionPipeline
.startRequestPipeline(request)
.let {
asyncTransport.execute(it).thenApply { response -> executionPipeline.startResponsePipeline(response) }
fun execute(request: Request): CompletableFuture<Response> {
val pipelineRequest =
try {
executionPipeline.startRequestPipeline(request)
} catch (e: Exception) {
throw ExpediaGroupPipelineExecutionException("exception while executing the request pipeline", e)
}

return asyncTransport
.execute(pipelineRequest)
.thenApply { response ->
try {
executionPipeline.startResponsePipeline(response)
} catch (e: Exception) {
throw ExpediaGroupPipelineExecutionException("exception while executing the response pipeline", e)
}
}.exceptionally { e ->
if (e.cause is ExpediaGroupPipelineExecutionException) throw e.cause as ExpediaGroupPipelineExecutionException
throw ExpediaGroupTransportException("Failed to execute the request", e)
}
}

override fun dispose() = asyncTransport.dispose()

companion object {
private fun loadTransport(): AsyncTransport =
ServiceLoader.load(AsyncTransport::class.java).firstOrNull().getOrThrow {
ExpediaGroupConfigurationException(
"No AsyncTransport implementation found. Please include valid HTTP client dependency",
"No AsyncTransport implementation found. Please include valid SDK transport dependency",
)
}
}
Expand Down
Loading

0 comments on commit 3feedf8

Please sign in to comment.