Skip to content

Commit c17ccef

Browse files
committed
Abstract the WebView request interception into a separate class, so it's more clear
1 parent ccd7723 commit c17ccef

File tree

2 files changed

+63
-35
lines changed

2 files changed

+63
-35
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package dev.hotwire.turbo.http
2+
3+
import android.webkit.WebResourceRequest
4+
import android.webkit.WebResourceResponse
5+
import dev.hotwire.turbo.session.TurboSession
6+
import dev.hotwire.turbo.util.logEvent
7+
8+
internal class TurboWebViewRequestInterceptor(val session: TurboSession) {
9+
private val offlineRequestHandler get() = session.offlineRequestHandler
10+
private val httpRepository get() = session.httpRepository
11+
private val currentVisit get() = session.currentVisit
12+
13+
fun interceptRequest(request: WebResourceRequest): WebResourceResponse? {
14+
val requestHandler = offlineRequestHandler ?: return null
15+
16+
if (!shouldInterceptRequest(request)) {
17+
return null
18+
}
19+
20+
val url = request.url.toString()
21+
val isCurrentVisitRequest = url == currentVisit?.location
22+
val result = httpRepository.fetch(requestHandler, request)
23+
24+
return if (isCurrentVisitRequest) {
25+
logCurrentVisitResult(url, result)
26+
currentVisit?.completedOffline = result.offline
27+
28+
// If the request resulted in a redirect, don't return the response. This
29+
// lets the WebView handle the request/response and Turbo can see the redirect,
30+
// so a redirect "replace" visit can be proposed.
31+
when (result.redirectToLocation) {
32+
null -> result.response
33+
else -> null
34+
}
35+
} else {
36+
result.response
37+
}
38+
}
39+
40+
private fun shouldInterceptRequest(request: WebResourceRequest): Boolean {
41+
return request.method.equals("GET", ignoreCase = true) &&
42+
request.url.scheme?.startsWith("HTTP", ignoreCase = true) == true
43+
}
44+
45+
private fun logCurrentVisitResult(url: String, result: TurboHttpRepository.Result) {
46+
logEvent(
47+
"location" to url,
48+
"redirectToLocation" to result.redirectToLocation.toString(),
49+
"statusCode" to (result.response?.statusCode ?: "<none>"),
50+
"completedOffline" to result.offline
51+
)
52+
}
53+
54+
private fun logEvent(vararg params: Pair<String, Any>) {
55+
val attributes = params.toMutableList().apply {
56+
add(0, "session" to session.sessionName)
57+
}
58+
logEvent("interceptRequest", attributes)
59+
}
60+
}

turbo/src/main/kotlin/dev/hotwire/turbo/session/TurboSession.kt

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ import androidx.webkit.WebViewFeature.*
1717
import dev.hotwire.turbo.config.TurboPathConfiguration
1818
import dev.hotwire.turbo.config.screenshotsEnabled
1919
import dev.hotwire.turbo.delegates.TurboFileChooserDelegate
20-
import dev.hotwire.turbo.http.TurboHttpClient
21-
import dev.hotwire.turbo.http.TurboHttpRepository
22-
import dev.hotwire.turbo.http.TurboOfflineRequestHandler
23-
import dev.hotwire.turbo.http.TurboPreCacheRequest
20+
import dev.hotwire.turbo.http.*
2421
import dev.hotwire.turbo.nav.TurboNavDestination
2522
import dev.hotwire.turbo.util.*
2623
import dev.hotwire.turbo.views.TurboWebView
@@ -54,6 +51,7 @@ class TurboSession internal constructor(
5451
internal var restorationIdentifiers = SparseArray<String>()
5552
internal val context: Context = activity.applicationContext
5653
internal val httpRepository = TurboHttpRepository(activity.lifecycleScope)
54+
internal val requestInterceptor = TurboWebViewRequestInterceptor(this)
5755
internal val fileChooserDelegate = TurboFileChooserDelegate(this)
5856

5957
// User accessible
@@ -648,37 +646,7 @@ class TurboSession internal constructor(
648646
}
649647

650648
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
651-
val requestHandler = offlineRequestHandler ?: return null
652-
653-
if (!request.method.equals("GET", ignoreCase = true) ||
654-
request.url.scheme?.startsWith("HTTP", ignoreCase = true) != true
655-
) {
656-
return null
657-
}
658-
659-
val url = request.url.toString()
660-
val isCurrentVisitRequest = url == currentVisit?.location
661-
val result = httpRepository.fetch(requestHandler, request)
662-
663-
return if (isCurrentVisitRequest && result.redirectToLocation != null) {
664-
// Let Turbo see the redirect, so a redirect "replace" visit can be proposed
665-
logEvent("shouldInterceptRequest",
666-
"location" to url,
667-
"redirectToLocation" to result.redirectToLocation,
668-
"statusCode" to (result.response?.statusCode ?: "<none>")
669-
)
670-
null
671-
} else if (isCurrentVisitRequest) {
672-
logEvent("shouldInterceptRequest",
673-
"location" to url,
674-
"statusCode" to (result.response?.statusCode ?: "<none>"),
675-
"completedOffline" to result.offline
676-
)
677-
currentVisit?.completedOffline = result.offline
678-
result.response
679-
} else {
680-
result.response
681-
}
649+
return requestInterceptor.interceptRequest(request)
682650
}
683651

684652
override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceErrorCompat) {

0 commit comments

Comments
 (0)