Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: WebView shouldInterceptRequest not adding RequestProperties in the WebView

I am intercepting requests from the webview using shouldInterceptRequest

below is my code for returning my WebResourceResponse

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static WebResourceResponse handleRequestViaUrlOnly(WebResourceRequest webResourceRequest){
        String url = webResourceRequest.getUrl().toString();
        Log.i("intercepting req....!!!", url);
        String ext = MimeTypeMap.getFileExtensionFromUrl(url);
        String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext);

        try {
            HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setRequestProperty("Sample-Header", "hello");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            return new WebResourceResponse(mime, "UTF-8", conn.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

I call this method inside my CustomWebViewClient

class CustomWebViewClient extends WebViewClient {

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        return handleRequestViaUrlOnly(request);
    }
}

However, when I check the Request Headers from the WebView remote debugger in chrome://inspect/#devices.

The additional RequestProperty that I added is not present.

conn.setRequestProperty("Sample-Header", "hello");

The Sample-Header is not present in the Request Headers in the WebView.

Am I missing something? I'll appreciate any help.

like image 894
Aaron Avatar asked Jan 26 '17 08:01

Aaron


1 Answers

So the problem is that when you are passing conn.getInputStream() it gives only data. Response headers could be extracted by conn.getHeaderFields(). Also you will not be able to get your extra header back unless server supports it and CORS not involved. Here is wireshark output of the connection

GET /~fdc/sample.html HTTP/1.1
Sample-Header: hello
Content-Type: application/x-www-form-urlencoded
User-Agent: Dalvik/2.1.0 (Linux; U; Android 7.1; Android SDK built for x86_64 Build/NPF26K)
Host: www.columbia.edu
Connection: Keep-Alive
Accept-Encoding: gzip
Content-Length: 0

HTTP/1.1 200 OK
Date: Wed, 01 Mar 2017 09:06:58 GMT
Server: Apache
Last-Modified: Thu, 22 Apr 2004 15:52:25 GMT
Accept-Ranges: bytes
Vary: Accept-Encoding,User-Agent
Content-Encoding: gzip
Content-Length: 8664
Keep-Alive: timeout=15, max=99
Connection: Keep-Alive
Content-Type: text/html

As you can see there is no Sample-Header: hello header in response.

Here is the simple code that will construct WebResourceResponse headers from response and append your custom header to it:

webView.setWebViewClient(new WebViewClient() {
    private Map<String, String> convertResponseHeaders(Map<String, List<String>> headers) {
        Map<String, String> responseHeaders = new HashMap<>();
        responseHeaders.put("Sample-Header", "hello");

        for (Map.Entry<String, List<String>> item : headers.entrySet()) {
            List<String> values = new ArrayList<String>();

            for (String headerVal : item.getValue()) {
                values.add(headerVal);
            }
            String value = StringUtil.join(values, ",");
            Log.e(TAG, "processRequest: " + item.getKey() + " : " + value);

            responseHeaders.put(item.getKey(), value);
        }

        return responseHeaders;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        final String method = request.getMethod();
        final String url = request.getUrl().toString();
        Log.d(TAG, "processRequest: " + url + " method " + method);
        String ext = MimeTypeMap.getFileExtensionFromUrl(url);
        String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext);

        try {
            HttpURLConnection conn = (HttpURLConnection)new URL(url).openConnection();
            conn.setRequestMethod(method);
            conn.setRequestProperty("Sample-Header", "hello");
            conn.setDoInput(true);
            conn.setUseCaches(false);

            Map<String, String> responseHeaders = convertResponseHeaders(conn.getHeaderFields());

            responseHeaders.put("Sample-Header", "hello");

            return new WebResourceResponse(
                    mime,
                    conn.getContentEncoding(),
                    conn.getResponseCode(),
                    conn.getResponseMessage(),
                    responseHeaders,
                    conn.getInputStream()
                    );

        } catch (Exception e) {
            Log.e(TAG, "shouldInterceptRequest: " + e);
        }
        return null;
    }
});
like image 169
j2ko Avatar answered Nov 15 '22 00:11

j2ko