Skip to content

Instantly share code, notes, and snippets.

@gold24park
Created March 28, 2023 06:10
Show Gist options
  • Save gold24park/71715a56c1f483470142799fbab00e12 to your computer and use it in GitHub Desktop.
Save gold24park/71715a56c1f483470142799fbab00e12 to your computer and use it in GitHub Desktop.
An implementation of an OkHttp Interceptor that prevents duplicate requests within a given period
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import okio.Buffer
import java.math.BigInteger
import java.security.MessageDigest
import java.util.concurrent.ConcurrentHashMap
class DuplicateCheckInterceptor(private val period: Long) : Interceptor {
private val requestMap = ConcurrentHashMap<String, RequestInfo>()
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val hash = request.createHash()
val requestInfo = requestMap[hash]
if (System.currentTimeMillis() - (requestInfo?.lastExecutionTime ?: 0L) < period) {
val originalResponse = requestInfo!!.response
return requestInfo.response.newBuilder()
.body(requestInfo.responseBody.toResponseBody(originalResponse.body?.contentType()))
.build()
}
val response = chain.proceed(request)
requestMap[hash] = RequestInfo(
response,
response.peekBody(Long.MAX_VALUE).bytes(),
System.currentTimeMillis()
)
return response
}
private fun md5(input: String): String {
val md = MessageDigest.getInstance("MD5")
return BigInteger(1, md.digest(input.toByteArray())).toString(16).padStart(32, '0')
}
private fun Request.createHash(): String {
return md5("${url}.${body?.bodyToString()}")
}
private fun RequestBody.bodyToString(): String {
return try {
val buffer = Buffer()
this.writeTo(buffer)
buffer.readUtf8()
} catch (e: Exception) {
""
}
}
data class RequestInfo(
val response: Response,
val responseBody: ByteArray,
val lastExecutionTime: Long
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as RequestInfo
if (response != other.response) return false
if (!responseBody.contentEquals(other.responseBody)) return false
if (lastExecutionTime != other.lastExecutionTime) return false
return true
}
override fun hashCode(): Int {
var result = response.hashCode()
result = 31 * result + responseBody.contentHashCode()
result = 31 * result + lastExecutionTime.hashCode()
return result
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment