Coverage Summary for Class: ResponseMetadata (dev.skymansandy.wiretap.okhttp.http)
| Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| ResponseMetadata |
100%
(1/1)
|
100%
(1/1)
|
|
100%
(10/10)
|
100%
(47/47)
|
/*
* Copyright (c) 2026 skymansandy. All rights reserved.
*/
package dev.skymansandy.wiretap.okhttp.http
import okhttp3.Interceptor
import okhttp3.Response
import java.security.cert.X509Certificate
internal data class ResponseMetadata(
val responseHeaders: Map<String, String>,
val responseBody: String?,
val protocol: String,
val remoteAddress: String?,
val tlsProtocol: String?,
val cipherSuite: String?,
val certificateCn: String?,
val issuerCn: String?,
val certificateExpiry: String?,
)
internal fun extractResponseMetadata(
response: Response,
chain: Interceptor.Chain,
maxContentLength: Int = 500 * 1024,
): ResponseMetadata {
val responseHeaders = response.headers.toMap()
val responseBody = try {
response.peekBody(maxContentLength.toLong()).string()
} catch (_: Exception) {
null
}
val protocol = response.protocol.toString()
val remoteAddress = try {
chain.connection()?.route()?.socketAddress?.let { "${it.hostName}:${it.port}" }
} catch (_: Exception) {
null
}
val handshake = response.handshake
val tlsProtocol = handshake?.tlsVersion?.javaName
val cipherSuite = handshake?.cipherSuite?.javaName
val peerCert = try {
handshake?.peerCertificates?.firstOrNull() as? X509Certificate
} catch (_: Exception) {
null
}
val certificateCn = peerCert?.extractCn { subjectX500Principal }
val issuerCn = peerCert?.extractCn { issuerX500Principal }
val certificateExpiry = peerCert?.notAfter?.toString()
return ResponseMetadata(
responseHeaders = responseHeaders,
responseBody = responseBody,
protocol = protocol,
remoteAddress = remoteAddress,
tlsProtocol = tlsProtocol,
cipherSuite = cipherSuite,
certificateCn = certificateCn,
issuerCn = issuerCn,
certificateExpiry = certificateExpiry,
)
}
private fun X509Certificate.extractCn(
principal: X509Certificate.() -> javax.security.auth.x500.X500Principal,
): String? = principal().name
?.split(",")
?.firstOrNull { it.trimStart().startsWith("CN=") }
?.substringAfter("CN=")
?.trim()