[JAVA] Choses à oublier lors de l'interception d'une requête avec Android WebView # shouldInterceptRequest

Lorsque vous souhaitez implémenter indépendamment la gestion des réponses HTTP et le délai d'expiration dans Android WebView, vous pouvez remplacer shouldInterceptRequest et implémenter la communication HTTP indépendamment.

Puisqu'il s'agit d'un échantillon, il s'agit d'une implémentation approximative, mais disons que vous l'avez implémentée comme suit.

override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? {
    val latch = CountDownLatch(1)
    var res: InputStream? = null

    val call = createOkHttpClient().newCall(Request.Builder().url(request?.url.toString()).method("POST", RequestBody.create(null, "hoge")).build())
    call.enqueue(object: Callback {
        override fun onFailure(call: Call, e: IOException) {
            latch.countDown()
        }

        override fun onResponse(call: Call, response: Response) {
            res = response.body()?.byteStream()
            latch.countDown()
        }
    })

    latch.await()
    return WebResourceResponse("text/html", "UTF-8",res)
}

private val cookieStore = HashMap<String, MutableList<Cookie>>()

fun createOkHttpClient(): OkHttpClient {
    return OkHttpClient.Builder()
        .cookieJar(object: CookieJar {
            override fun saveFromResponse(url: HttpUrl, cookies: MutableList<Cookie>) {
                cookieStore[url.host()] = cookies
        }

            override fun loadForRequest(url: HttpUrl): MutableList<Cookie> {
                val cookies = cookieStore[url.host()]
                return cookies ?: ArrayList()
            }
        })
        .build()
}

Mais soyez prudent lorsque vous l'utilisez. Par exemple, considérons le cas de l'obtention du code HTML suivant.

<html>                                                                                                                                                                                                                                        
<body>
<script type="text/javascript">
  function doPost() {
    document.TestForm.submit();
  }
</script>

<h1>Test</h1>

<form id="TestForm" name="TestForm" action="http://192.168.100.2:3000/hoge" method="post">
  <input type="hidden" name="hoge" value="hogeVal"/>
  <input type="hidden" name="fuga" value="fugaVal"/>
  <input type="submit" value="submit">
</form>
<script type="text/javascript">
  doPost();
</script>
</body>
</html>

Puisque WebView a une fonction d'analyse HTML, la fonction doPost est appelée lors de la lecture du code HTML ci-dessus, et pour le http: //192.168.100.2: 3000 / hoge``` défini dans la balise

. Et envoyez automatiquement la demande.

À ce stade, si WebView est responsable du chargement des ressources avec shouldInterceptRequest (à moins qu'il ne remplace shouldInterceptRequest), La valeur de l'attribut caché de la balise \ <input > est automatiquement POSTÉE, mais lorsque le développeur implémente la requête indépendamment avec OkHTTP etc., il / elle doit analyser le contenu HTML et l'ajouter par lui-même. ne pas. (Par défaut, la valeur de l'attribut masqué n'est pas attribuée)

Configurons le serveur suivant et regardons le journal.

{-# LANGUAGE OverloadedStrings #-}                                                                                                                                                                                                            
module Main where

import Web.Scotty
import Control.Monad.IO.Class (liftIO)

main :: IO ()
main = scotty 3000 $ do
  post "/test.html" $ file "./static/test.html" >> setHeader "Content-Type" "text/html"
  post "/hoge" $ do
    (liftIO . putStrLn $ ("Access to /hoge. Headers: " :: String)) >> headers >>= liftIO . print
    (liftIO . putStrLn $ ("Params: " :: String)) >> params >>= liftIO . print
    text "hoge success"

Si vous ne remplacez pas shouldInterceptRequest


Access to /hoge. Headers: 
[("Host","192.168.100.151:3000"),("Connection","keep-alive"),("Content-Length","25"),("Cache-Control","max-age=0"),("Origin","http://192.168.100.151:3000"),("Upgrade-Insecure-Requests","1"),("Content-Type","application/x-www-form-urlencoded"),("User-Agent","Mozilla/5.0 (Linux; Android 9; Android SDK built for x86 Build/PSR1.180720.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.158 Mobile Safari/537.36"),("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"),("Referer","http://192.168.100.151:3000/test.html"),("Accept-Encoding","gzip, deflate"),("Accept-Language","ja-JP,en-US;q=0.9"),("X-Requested-With","com.badlogic.masaki.webviewjsinterfacesample")]
Params: 
[("hoge","hogeVal"),("fuga","fugaVal")]

Quand shouldIntercept est remplacé dans l'implémentation ci-dessus


Access to /hoge. Headers: 
[("Content-Length","4"),("Host","192.168.100.151:3000"),("Connection","Keep-Alive"),("Accept-Encoding","gzip"),("User-Agent","okhttp/3.10.0")]
Params: 
[]

Le contenu défini dans l'attribut caché de HTML n'est pas POSTÉ. Si tel est le cas, la réponse prévue ne sera pas renvoyée par le serveur. De plus, les informations d'en-tête telles que User-Agent seront également remplacées, soyez donc prudent lorsque vous remplacez shouldInterceptRequest.

L'analyse HTML est requise pour POST la valeur de l'attribut masqué. Diverses informations sont déjà disponibles ici.

Comment obtenir le contenu du HTML a été utile comme ci-dessous. https://stackoverflow.com/questions/8200945/how-to-get-html-content-from-a-webview

Comment définir le paramètre POST de l'application / x-www-form-urlencoded avec OkHttp est comme suit Cela a été utile. https://stackoverflow.com/questions/35756264/how-do-i-post-data-using-okhttp-library-with-content-type-x-www-form-urlencoded

J'ai dit la même chose dans Article précédent, mais comme le but de WebView est de rendre HTML, ce n'est pas comme l'utiliser pour les appels WebAPI. ..

Recommended Posts

Choses à oublier lors de l'interception d'une requête avec Android WebView # shouldInterceptRequest
Points à surveiller lors de la création d'un framework
Éléments à prendre en compte lors du choix de l'architecture d'un nouveau système
Éléments à prendre en compte lors de l'exécution d'un travail spécifié à l'aide de Spring Batch
Envoyer une pull request à GitHub
Lancer une requête PATCH avec HttpURLConnection
Points à garder à l'esprit lors de l'utilisation d'Apache PDFBox® avec AWS Lambda
Envoyez une demande au backend après une authentification unique avec Spring Cloud Gateway
Remarques sur la marche à suivre lorsqu'une exception WebView ClassNotFoundException se produit dans JavaFX 12