Created
March 28, 2023 06:10
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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