Add AutoconfigFetcher interface

This commit is contained in:
cketti 2023-05-26 16:31:55 +02:00
parent f53d73630e
commit 0ab058656e
5 changed files with 66 additions and 56 deletions

View file

@ -63,7 +63,7 @@ private fun createAutoconfigDiscovery(
okHttpClient: OkHttpClient,
urlProvider: AutoconfigUrlProvider,
): AutoconfigDiscovery {
val fetcher = AutoconfigFetcher(okHttpClient)
val fetcher = OkHttpAutoconfigFetcher(okHttpClient)
val parser = SuspendableAutoconfigParser(AutoconfigParser())
return AutoconfigDiscovery(urlProvider, fetcher, parser)
}

View file

@ -1,58 +1,8 @@
package app.k9mail.autodiscovery.autoconfig
import com.fsck.k9.logging.Timber
import java.io.IOException
import java.io.InputStream
import kotlin.coroutines.resume
import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.Call
import okhttp3.Callback
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
internal class AutoconfigFetcher(private val okHttpClient: OkHttpClient) {
suspend fun fetchAutoconfigFile(url: HttpUrl): InputStream? {
return try {
performHttpRequest(url)
} catch (e: IOException) {
Timber.d(e, "Error fetching URL: %s", url)
null
}
}
private suspend fun performHttpRequest(url: HttpUrl): InputStream? {
return suspendCancellableCoroutine { cancellableContinuation ->
val request = Request.Builder()
.url(url)
.build()
val call = okHttpClient.newCall(request)
cancellableContinuation.invokeOnCancellation {
call.cancel()
}
val responseCallback = object : Callback {
override fun onFailure(call: Call, e: IOException) {
cancellableContinuation.cancel(e)
}
override fun onResponse(call: Call, response: Response) {
if (response.isSuccessful) {
val inputStream = response.body?.byteStream()
cancellableContinuation.resume(inputStream)
} else {
// We don't care about the body of error responses.
response.close()
cancellableContinuation.resume(null)
}
}
}
call.enqueue(responseCallback)
}
}
internal interface AutoconfigFetcher {
suspend fun fetchAutoconfigFile(url: HttpUrl): InputStream?
}

View file

@ -99,7 +99,7 @@ fun createMxLookupAutoconfigDiscovery(okHttpClient: OkHttpClient): MxLookupAutoc
baseDomainExtractor = baseDomainExtractor,
subDomainExtractor = RealSubDomainExtractor(baseDomainExtractor),
urlProvider = IspDbAutoconfigUrlProvider(),
fetcher = AutoconfigFetcher(okHttpClient),
fetcher = OkHttpAutoconfigFetcher(okHttpClient),
parser = SuspendableAutoconfigParser(AutoconfigParser()),
)
}

View file

@ -0,0 +1,60 @@
package app.k9mail.autodiscovery.autoconfig
import com.fsck.k9.logging.Timber
import java.io.IOException
import java.io.InputStream
import kotlin.coroutines.resume
import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.Call
import okhttp3.Callback
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request.Builder
import okhttp3.Response
internal class OkHttpAutoconfigFetcher(
private val okHttpClient: OkHttpClient,
) : AutoconfigFetcher {
override suspend fun fetchAutoconfigFile(url: HttpUrl): InputStream? {
return try {
performHttpRequest(url)
} catch (e: IOException) {
Timber.d(e, "Error fetching URL: %s", url)
null
}
}
private suspend fun performHttpRequest(url: HttpUrl): InputStream? {
return suspendCancellableCoroutine { cancellableContinuation ->
val request = Builder()
.url(url)
.build()
val call = okHttpClient.newCall(request)
cancellableContinuation.invokeOnCancellation {
call.cancel()
}
val responseCallback = object : Callback {
override fun onFailure(call: Call, e: IOException) {
cancellableContinuation.cancel(e)
}
override fun onResponse(call: Call, response: Response) {
if (response.isSuccessful) {
val inputStream = response.body?.byteStream()
cancellableContinuation.resume(inputStream)
} else {
// We don't care about the body of error responses.
response.close()
cancellableContinuation.resume(null)
}
}
}
call.enqueue(responseCallback)
}
}
}

View file

@ -11,8 +11,8 @@ import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.Test
class AutoconfigFetcherTest {
private val fetcher = AutoconfigFetcher(OkHttpClient.Builder().build())
class OkHttpAutoconfigFetcherTest {
private val fetcher = OkHttpAutoconfigFetcher(OkHttpClient.Builder().build())
@Test
fun shouldHandleNonexistentUrl() = runTest {