Add AutoconfigFetcher
interface
This commit is contained in:
parent
f53d73630e
commit
0ab058656e
5 changed files with 66 additions and 56 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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?
|
||||
}
|
||||
|
|
|
@ -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()),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {
|
Loading…
Reference in a new issue