Adding custom header to all requests in shouldInterceptRequest Android webview - android

I want to add custom Headers to requests in the webview. I think it should be possible to do it in shouldInterceptRequest.. Since my minimum API level is less than 21 shouldInterceptRequest (final WebView view, final String url) is also called and therefore I need to add headers here as well but I am not sure how.
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
request.getRequestHeaders().put("ClientId", "ANDROID");
request.getRequestHeaders().put("Tokon", token);
}
return super.shouldInterceptRequest(view, request);
}
#Override
public WebResourceResponse shouldInterceptRequest(final WebView view, final String url) {
// I need to updated the header here
return super.shouldInterceptRequest(view, url);
}
There is a suggestion to use view.loadUrl(url,headers) but this does not work either.

The difficulty you run into with pre API 21 is the shouldInterceptRequest only provides the intercepted URL and the webview without the body of the request. I ran into this same issue and discovered the following GitHub repository
https://github.com/KeejOow/android-post-webview
The important part of this project is interceptheader.html in the assets folder. This html contains javascript that is inserted at the top of every html response the webview loads. This JS intercepts every form and ajax submission from the page and loads the body data into a java class. Next the shouldInterceptRequest method determines whether the request is POST or GET (you only get those two, unfortunately) based on whether there is any data in the body.
Finally, once it has marshalled all the relevant information, it performs the request by itself (instead of passing it off to Android), returning the resulting WebResourceResponse.
Be warned that the repository has seen some aging. I had to do some fiddling to get pages to work as I wanted them.
The best place to add your headers is in the InterceptingWebViewClient class under shouldInterceptRequest.
conn.setRequestProperty("header-name", value);

Related

Ways for analysis of WebResourceResponse

I want to analyze all requests sent from WebView.
For this, I have WebViewClient and shouldInterceptRequest overridden.
I can see requests, but I would like to see what webView will receive in response. I need this for analysis, I do not have need to change response.
Line bellow gives null,
WebResourceResponse response = super.shouldInterceptRequest(view, request);
I know, that shouldInterceptRequest() return null, means that no one intercept the request, and the webView will load the origin URL.
But, I would like to see this WebResourceResponse and do not implement it by myself.Thanks!!

Adding custom header to WebView by adding headers to WebResourceRequest's headers in shouldInterceptRequest doesn't work

I need to add a custom header to a page loading in WebView, but it doesn't work, header is not set:
#Override
public WebResourceResponse shouldInterceptRequest (WebView view, WebResourceRequest request)
{
request.getRequestHeaders().add("MyHeader","MyValue");
return super.shouldInterceptRequest(view, request);
}
What I am doing wrong here? I'm running on Android 5.
I've seen many answers on SO saying that you have to do the HTTP request and return WebResourceResponse yourself. Is this because even if you modify headers like I do, they are ignored?
I also trying to find the location in the Android source code of the call to
Where is the location of the call to the shouldInterceptRequest so I can see how it works myself, but I couldn't find it.
I found the answer myself, it's right there in docs:
If the return value is null, the WebView will continue to load the
resource as usual. Otherwise, the return response and data will be
used.
Moreover, a simple test shows the base implementation of WebViewClient.shouldInterceptRequest returns null. So the WebView basically continues to load resource as usual.
In other words, I cannot just add a value to header and expect it to be used.
I actually need to do the request myself and return the response.
Too bad there is no way to just modify header and have the default implementation use it.
I know I can set in headers by calling loadUrl method with headers, but the headers won't be used if I'm first loading a local page and then load online pages.
Default method implementation of shouldInterceptRequest provided in the WebViewClient is returning null, hence if we need additional headers to be set then we have to create WebResourceResponse and return it.
https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/android/webkit/WebViewClient.java
I was able to add a custom header to the response using this code in one of my shouldInterceptRequest handlers:
InputStream is = new ByteArrayInputStream(result.getBytes());
WebResourceResponse resp = new WebResourceResponse("text/html", null, is);
Map<String, String> hdrs = resp.getResponseHeaders();
Map<String, String> newHdrs = new HashMap<>();
if(hdrs != null) newHdrs.putAll(hdrs);
newHdrs.put("Access-Control-Allow-Origin", "*");
resp.setResponseHeaders(newHdrs);
return resp;
Note that this is 5 years after the original post and I'm coding to API 30

Intercept and Change Request Location in Android WebView

After looking around, I am unable to find an easy way to intercept requests made by the WebView and change the URL.
For example, I would like requests *.melange to actually route to localhost:8080 while keeping the original URL as the Host header.
It appears, at first glance, that the easiest method to achieve this sort of URL rewriting would be to use the "new" (API Level 21 or higher) shouldInterceptRequest, copy the values out of the WebResourceRequest to make the HTTP request manually then return a WebResourceResponse with the correct values. In my mind, there "should" be an easier way to do this.
Please let me know if I am missing something obvious. Thanks!
private class MyWebviewclient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.contains("melange"){
String newUrl = "http://localhost:8080"+url.split("melange")[1];
loadUrl(newUrl);
}
return false;
}
}
Now,
yourWebView.setWebViewClient(new MyWebviewclient());

shouldInterceptRequest on Android 4.4 KitKat

I have an App that uses custom schemes in Android WebViewClient's shouldInterceptRequest(WebView view, String url) and shouldOverrideUrlLoading(WebView view, String url) to intercept requests in a web application and use a native library to fetch resources from elsewhere in shouldInterceptRequest. This has worked fine up until Android 4.4 KitKat, where Google has made some crucial changes to the webView component.
http://developer.android.com/guide/webapps/migrating.html#URLs
Now the url received in shouldOverrideUrlLoading suddenly gets invalid, looking like this; custom-scheme:////my.pathname.com/. First I suspected the extra slashes were because Android did not think the url were valid RFC3986, but in a series of resource fetches (css, js, images), the url starts off correct and suddenly changes to the invalid format. The webView in Android 4.3 kept the url correctly as custom-scheme://my.pathname.com/. It seems like the base url suddenly changes to '/' instead of 'my.pathname.com'.
Then my attention changed to the fact that the webView 4.4 migration guide talks about:
If you call methods on WebView from any thread other than your app's UI thread, it can cause unexpected results. http://developer.android.com/guide/webapps/migrating.html#Threads
This also might be what I am experiencing, but I have not yet come up with a solution where I can use runOnUiThread() to fetch data with the native api and return it to the webView inside shouldInterceptRequest. Has anyone experienced something similar?
Here is a simplified version of my shouldInterceptRequest code:
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if (urlStartsWithKnownPrefix(url)) {
UrlFetchResult fetchRes = api.fetchUrl(url);
String charset = "utf-8";
String mime = fetchRes.getMimetype();
WebResourceResponse res = new WebResourceResponse(mime, charset, new ByteArrayInputStream(fetchRes.getResult()));
return res;
}
return null;
}
Are you using jquery-mobile by any chance? This sounds very similar to: How can I use relative urls in ajax requests within trigger.io apps on Android 4.4 (kitkat)?

Android WebView: Should shouldInterceptRequest be triggered by XmlHttpRequest

I'm trying to integrate a javascript plugin that loads some resources by using XmlHttpRequest calls. I want this script to run within a locally loaded page in WebView. As you might have guessed already, XmlHttpRequest calls are not allowed for local resources, so I promptly get the following error:
XMLHttpRequest cannot load file:///android_asset/resources.html. Cross
origin requests are only supported for HTTP.
At this point I thought that I could emulate the web server by intercepting the calls and then just loading the file myself, such as:
webView.setWebViewClient(new WebViewClient() {
#Override
public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
try {
if (url.contains("resources.html")) { //breakpoint here is not triggering
return new WebResourceResponse("text/html", "UTF-8", getAssets().open("resources.html"));
}
} catch (IOException e) {
return super.shouldInterceptRequest(view, url);
}
return super.shouldInterceptRequest(view, url);
}
});
The problem is that shouldInterceptRequest is not being called. The official documentation is very brief and doesn't specify what type of requests are intercepted. This article sort of implies that the method does intercept XmlHttpRequest calls, but it doesn't appear to be working.
Does anyone know if shouldInterceptRequest should be called after a XmlHttpRequest? If not, is there another way to do this? Thanks
In API level 16 WebSettings added methods setAllowFileAccessFromFileURLs() and setAllowUniversalAccessFromFileURLs(). Setting this to true for the webView might solve your problem.
As my testing on this, it seems that only external requests would be intercepted - you can try to modify the local references to be external as "http://foo.com/..." (instead of "file:///android_asset/...").

Categories

Resources