Git Product home page Git Product logo

android-request-inspector-webview's Introduction

Android Request Inspector WebView Release

Inspect and intercept full HTTP requests (including all headers, cookies and body) sent from Android WebViews.

This project is inspired by android-post-webview and request_data_webviewclient and some code was taken from both projects.

Installation

Step 1. Add the JitPack repository to your build file:

allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}

Step 2. Add the dependency

dependencies {
    implementation 'com.github.acsbendi:Android-Request-Inspector-WebView:1.0.6'
}

Get the latest version on JitPack

Usage

To log the requests (default functionality):

    val webView = WebView(this)
    webView.webViewClient = RequestInspectorWebViewClient(webView)

To manually process requests:

    val webView = WebView(this)
    webView.webViewClient = object : RequestInspectorWebViewClient(webView) {
        override fun shouldInterceptRequest(
            view: WebView,
            webViewRequest: WebViewRequest
        ): WebResourceResponse? {
            TODO("handle request manually based on data from webViewRequest and return custom response")
            return super.shouldInterceptRequest(view, webViewRequest)
        }
    }

Known limitations

Detailed data (e.g. request body) is not available for requests sent from iframes as it's not possible to execute JavaScript code in iframes in Android WebViews. One possible workaround to still inspect the requests sent from a specific iframe is to load its URL into a different WebView and attach RequestInspectorWebViewClient to that.

Contributions

All feedback, PRs, and issues are welcome!

License

The MIT License

See LICENSE

android-request-inspector-webview's People

Contributors

acsbendi avatar erdemtsynduev avatar kumold avatar xiaojieonly avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

android-request-inspector-webview's Issues

Hello! I've been using the following code to make calls and noticed that most of the requests made by the WebView are showing up in my console. However, some requests are not appearing in my console. Why is this happening?

Hello! I've been using the following code to make calls and noticed that most of the requests made by the WebView are showing up in my console. However, some requests are not appearing in my console. Why is this happening?
**
RequestInspectorWebViewClient requestInspector = new RequestInspectorWebViewClient(webview);
webview.setWebViewClient(requestInspector);**

getting recorded request doesn't work

recorded request fetched with condition url.contains(recordedRequest.url), but if url = "https://somedomain.com/some/paths/here" and there was a request with url https://somedomain.com/some/path it will give wrong request.
Fix might be comparing extensively all recorded requests with all options.

Get response.body from an intercepted request

It would be good to have a feature to capture the response body as well.

Desired Syntax

val response = super.shouldInterceptRequest(view, webViewRequest)
println(response.body)
return response

Request is not always captured when page sends it right after loading

Hello! I'm loading a webpage that is always doing the same POST request and most of the times I'm able to get request body using this library. However, sometimes when shouldInterceptRequest() is called, webViewRequest.type is HTML instead of XML_HTTP and in that case POST request body is not available. Please note that webViewRequest.method is always POST as expected.

Any idea of what might be happening and how to fix this? Thank you

java.util.ConcurrentModificationException at RequestInspectorJavaScriptInterface.findRecordedRequestForUrl

Getting a rare crash in Crashlytics (library version 1.0.2):

Exception: java.util.ConcurrentModificationException:
       at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1029)
       at java.util.ArrayList$Itr.next(ArrayList.java:982)
       at com.acsbendi.requestinspectorwebview.RequestInspectorJavaScriptInterface.findRecordedRequestForUrl(RequestInspectorJavaScriptInterface.kt:21)
       at com.acsbendi.requestinspectorwebview.RequestInspectorWebViewClient.shouldInterceptRequest(RequestInspectorWebViewClient.kt:29)
       at WV.la.a(chromium-TrichromeWebViewGoogle.aab-stable-584517231:80)
       at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(chromium-TrichromeWebViewGoogle.aab-stable-584517231:15)

There is an ArrayList in the library source code for RequestInspectorJavaScriptInterface:
private val recordedRequests = ArrayList<RecordedRequest>()

I think there should probably be a CopyOnWriteArrayList or maybe a ConcurrentMap instead of ArrayList, or an immutable collection, or maybe another way to ensure thread-safety for correct behavior of concurrent find() and add() calls.

Got ConcurrentModificationException

I tried to use OkHttp to provide fake response for all requests:

webViewClient = object : RequestInspectorWebViewClient(this@apply) {

    private val httpClient = OkHttpClient()

    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    override fun shouldInterceptRequest(
        view: WebView,
        webViewRequest: WebViewRequest
    ): WebResourceResponse {

        val request = Request.Builder()
            .url(BASE_URL + webViewRequest.url)
            .method(
                webViewRequest.method,
                (if (HttpMethod.permitsRequestBody(webViewRequest.method)) webViewRequest.body else null
                    ?.toRequestBody(webViewRequest.headers["content-type"]?.toMediaTypeOrNull())
            )
            .headers(webViewRequest.headers.toHeaders())
            .build()

        val response = try {
            httpClient.newCall(request).execute()
        } catch (e: Exception) {
            Log.e("WebView", "Request failed at " + request.url)
            return WebResourceResponse(
                "text/plain",
                "utf-8",
                InputStream.nullInputStream()
            )
        }

        Log.d(
            "WebView",
            "${response.protocol} ${response.request.method} ${response.request.url}"
        )

        val type = response.headers["content-type"]?.toMediaTypeOrNull()
        return WebResourceResponse(
            if (type != null)
                "${type.type}/${type.subtype}"
            else null,
            response.headers["content-encoding"] ?: "utf-8",
            response.code,
            response.message.ifEmpty { getDefaultMessage(response.code) },
            response.headers.toMultimap().mapValues { it.value.first() },
            response.body?.byteStream()
        )
    }
}

But I got this error from time to time:

FATAL EXCEPTION: main
Process: com.example.browser, PID: 14726
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.next(ArrayList.java:860)
	at com.acsbendi.requestinspectorwebview.RequestInspectorJavaScriptInterface.findRecordedRequestForUrl(RequestInspectorJavaScriptInterface.kt:21)
	at com.acsbendi.requestinspectorwebview.RequestInspectorWebViewClient.shouldInterceptRequest(RequestInspectorWebViewClient.kt:29)
	at K9.a(chromium-TrichromeWebViewGoogle6432.aab-beta-535902244:80)
	at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(chromium-TrichromeWebViewGoogle6432.aab-beta-535902244:15)

Is possible to change body content?

First of all, I deeply appreciate this very good project.
I wonder If a changed request does not make any problem when I change some body content.

ex.
override fun shouldInterceptRequest( view: WebView, webViewRequest: WebViewRequest ): WebResourceResponse? {
webViewRequest.body = changedBodyString
return super.shouldInterceptRequest(view, webViewRequest) }

Getting this error

failed to set the 'responsetype' property on 'xmlhttprequest': the response type cannot be changed for synchronous requests made from a document.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.