Orchestration SDKs

Customizing requests from the DaVinci module on Android

PingOne Android

All modules in the Orchestration SDK for Android use an HTTP client abstraction provided by the Network module to make network requests.

You can use this HTTP client to create interceptors, that can modify requests before they’re sent, or inspect responses after they’re received.

For example, you can add or customize:

  • Query parameters

  • Headers

  • Cookies

  • Body data

You can add query parameters when authenticating to PingOne without creating an interceptor by using the additionalParameters property.

Step 1. Creating an HTTP client

To customize network requests, initialize and configure an HttpClient instance:

Initializing HttpClient on Android
import com.pingidentity.network.ktor.HttpClient
import com.pingidentity.logger.Logger
import kotlin.time.DurationUnit
import kotlin.time.toDuration

val customHttpClient = HttpClient {
    // Optional: Configure timeout (default: 15 seconds)
    timeout = 30.toDuration(DurationUnit.SECONDS)
    // Optional: Configure logging (default: Logger.WARN)
    logger = Logger.logger  // Use default application logger
}

Use the following properties to configure the HTTP client:

timeout

The number of seconds to wait before each request times out.

Default is 15 seconds.

logger

The logger that HttpClient uses for output.

Available options are:

Value Description

Logger.STANDARD

Outputs all log messages to the Android Logcat.

Logger.WARN

Outputs only warning and error log messages to the Android Logcat.

Logger.NONE

Prevents all log messages.

Logger.logger

Use whichever logger is already configured in the application.

Default is Logger.WARN.

Step 2. Adding interceptors to the HTTP client

Add custom interceptors to the HTTP client to modify requests before they’re sent or inspect responses after they’re received.

Adding request interceptors

To add an interceptor that applies to all outgoing requests from a module, use the onRequest method.

To customize the requests, pass in your own values for headers, query parameters, cookies, or body parameters.

  • Headers

  • Query parameters

  • Cookies

  • Body data

Customizing headers using request interceptors in HttpClient
val customHttpClient = HttpClient {
    // Add an example correlation ID
    onRequest {
        header("X-Correlation-ID", UUID.randomUUID().toString())
    }

    // Add a custom header conditionally
    onRequest {
        if (isDebugMode) {
            header("X-Debug", "true")
        }
    }
}
Customizing query parameters using request interceptors in HttpClient
val customHttpClient = HttpClient {
    onRequest {
        // Add custom query parameters
        parameter("lang", "en-UK")
        parameter("brand", "example.co.uk")
    }
}
Customizing cookies using request interceptors in HttpClient
val customHttpClient = HttpClient {
    onRequest {
        // Add custom cookies
        cookie("sessionId=abc123; Path=/; HttpOnly")
    }
}
Customizing body data using request interceptors in HttpClient
val customHttpClient = HttpClient {
    onRequest {
        // Add JSON body data to POST requests
        post(buildJsonObject {
            put("name", "Babs Jensen")
            put("email", "bjensen@example.com")
        })
    }

    onRequest {
        // Add JSON body data to PUT requests
        put(buildJsonObject {
            put("name", "Updated Name")
            put("email", "updated@example.com")
        })
    }
}

Adding response interceptors

To add an interceptor that can inspect all incoming responses to a module, use the onResponse method.

To inspect the response, capture the values of the incoming headers, cookies, body parameters, and HTTP response status.

You can also capture the original request object that triggered the response, which can be useful for auditing or debugging purposes.

  • HTTP Status

  • Headers

  • Cookies

  • Body data

  • Original request

Capturing HTTP status codes using response interceptors in HttpClient
val customHttpClient = HttpClient {
    // Check the HTTP status code of a response
    onResponse {
        val statusCode = status

        if (statusCode.isSuccess()) {
            // Handle 200-299 status codes
            processSuccess(body())
        } else {
            when (statusCode) {
                400 -> handleBadRequest()
                401 -> handleUnauthorized()
                404 -> handleNotFound()
                500 -> handleServerError()
                else -> handleOtherError(statusCode)
            }
        }
    }
}
Capturing headers using response interceptors in HttpClient
val customHttpClient = HttpClient {
    // Track response times using a header
    onResponse {
        val allHeaders = headers()
        val duration = header("X-Response-Time")

        analytics.trackResponseTime(duration)
    }
}
Capturing cookies using response interceptors in HttpClient
val customHttpClient = HttpClient {
    onResponse {
        // Capture cookies
        val allCookies = cookies()
    }
}
Capturing body data using response interceptors in HttpClient
val customHttpClient = HttpClient {
    onResponse {
        // Capture body data
        val allBodyData = body()
    }

}
Capturing the original request that caused a response
val customHttpClient = HttpClient {
    // Capture the original outgoing request
    onResponse {
        val originalRequest = request
    }
}

Step 3. Configuring the DaVinci module to use an HTTP client

Pass the name of your custom HTTP client to the DaVinci module in the httpClient parameter in the configuration:

Configuring the DaVinci module
val daVinci = DaVinci {
    // Custom HTTP client
    httpClient = customHttpClient

    // Other configuration
    module(Oidc) {
        clientId = "6c7eb89a-66e9-ab12-cd34-eeaf795650b2"
        discoveryEndpoint = "https://auth.pingone.com/3072206d-c6ce-ch15-m0nd-f87e972c7cc3/as/.well-known/openid-configuration"
        scopes = mutableSetOf("openid", "profile", "email")
        redirectUri = "com.example.demo://oauth2redirect"
    }
}

Step 4. Cleaning up an HTTP client

To help manage resources the HTTP client might use, call close() on the client when you have finished with it.

Closing an HTTP client
customHttpClient.close()