Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - Check if request is GET or POST

I need to check if the request is a POST or a GET in shouldInterceptRequest in my Android application. See code below:

public class CustomWebViewClient extends WebViewClient {

    ...

    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        if ("request is POST")
            Log.d("CustomWebViewClient", "request is a POST");
        else if ("request is GET")
            Log.d("CustomWebViewClient", "request is a GET");

        ...
    }
}

Is it possible to determine this in an extend of WebViewClient?

like image 886
MartinR Avatar asked Nov 05 '12 17:11

MartinR


2 Answers

It is possible by extending WebViewClient, but it might involve a bit more work than you expected. The callback methods in WebViewClient are called by JNI which you can't call to get headers and method, so your best bet is to use JavaScript.

This solution is based on kristof's comment on http://code.google.com/p/android/issues/detail?id=9122#c21

1. Create a file called post_interceptor.js and put it in res/raw

post_interceptor.js

HTMLFormElement.prototype._submit = HTMLFormElement.prototype.submit;
HTMLFormElement.prototype.submit = interceptor;

window.addEventListener('submit', function(e) {
    interceptor(e);
}, true);

function interceptor(e) {
var frm = e ? e.target : this;
    interceptor_onsubmit(frm);
    frm._submit();
}

function interceptor_onsubmit(f) {
    var jsonArr = [];
    for (i = 0; i < f.elements.length; i++) {
        var parName = f.elements[i].name;
        var parValue = f.elements[i].value;
        var parType = f.elements[i].type;

        jsonArr.push({
            name : parName,
            value : parValue,
            type : parType
        });
    }

    window.interception.customSubmit(JSON.stringify(jsonArr),
            f.attributes['method'] === undefined ? null : f.attributes['method'].nodeValue,
            f.attributes['enctype'] === undefined ? null : f.attributes['enctype'].nodeValue);
}

lastXmlhttpRequestPrototypeMethod = null;
XMLHttpRequest.prototype.reallyOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
    lastXmlhttpRequestPrototypeMethod = method;
    this.reallyOpen(method, url, async, user, password);
};
XMLHttpRequest.prototype.reallySend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
    window.interception.customAjax(lastXmlhttpRequestPrototypeMethod, body);
    lastXmlhttpRequestPrototypeMethod = null;
    this.reallySend(body);
};

2. Create a Java class called JavascriptPostIntercept

Change package/class names as necessary.

JavascriptPostIntercept.java

public class JavascriptPostIntercept {

    public interface JavascriptPostInterceptInterface {
        public void nextMessageIsAjaxRequest(AjaxRequestContents contents);
        public void nextMessageIsFormRequest(FormRequestContents contents);
    }

    private static String sInterceptHeader;

    private JavascriptPostInterceptInterface mClient;

    public static String getInterceptHeader() {
        if (sInterceptHeader == null) {
            // Assuming you have your own stream to string implementation
            sInterceptHeader = StringUtils.readInputStream(
                Resources.getSystem().openRawResource(R.raw.post_interceptor));
        }
        return sInterceptHeader;
    }

    public static class AjaxRequestContents {
        private String mMethod;
        private String mBody;

        public AjaxRequestContents(String method, String body) {
            mMethod = method;
            mBody = body;
        }

        public String getMethod() {
            return mMethod;
        }

        public String getBody() {
            return mBody;
        }
    }

    public static class FormRequestContents {
        private String mJson;
        private String mMethod;
        private String mEnctype;

        public FormRequestContents(String json, String method, String enctype) {
            mJson = json;
            mMethod = method;
            mEnctype = enctype;
        }

        public String getJson() {
            return mJson;
        }

        public String getMethod() {
            return mMethod;
        }

        public String getEnctype() {
            return mEnctype;
        }
    }

    public JavascriptPostIntercept(JavascriptPostInterceptInterface client) {
        mClient = client;
    }

    @JavascriptInterface
    public void customAjax(final String method, final String body) {
        mClient.nextMessageIsAjaxRequest(new AjaxRequestContents(method, body));
    }

    @JavascriptInterface
    public void customSubmit(String json, String method, String enctype) {
        mClient.nextMessageIsFormRequest(new FormRequestContents(json, method, enctype));
    }
}

3. Create your WebViewClient subclass

The code below only gets the HTTP method of the latest request, which looks like enough for what you're asking, but obviously the other methods on AjaxRequestContents and FormSubmitContents will give you access to the post body and other stuff if you need it.

class MyWebViewClient extends WebViewClient implements JavascriptPostIntercept.JavascriptPostInterceptInterface {
    private String mLastRequestMethod = "GET";

    /// evaluate post_interceptor.js after the page is loaded
    @Override
    public void onPageFinished(WebView view, String url) {
        view.loadUrl("javascript: " + JavascriptPostIntercept.getInterceptHeader());
    }

    @TargetApi(11)
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        if (mLastRequestMethod.equals("POST")) {
            // do stuff here...
        } else if (mLastRequestMethod.equals("GET")) {
            // do other stuff here...
        }
        // return something here...
    }

    @Override
    public void nextMessageIsAjaxRequest(JavascriptPostIntercept.AjaxRequestContents contents) {
        mLastRequestMethod = contents.getMethod();
    }

    @Override
    public void nextMessageIsFormRequest(JavascriptPostIntercept.FormRequestContents contents) {
        mLastRequestMethod = contents.getMethod();
    }
}

4. Create the appropriate JS-Java links

MyWebViewClient webViewClient = new MyWebViewClient();
mWebView.setWebViewClient(webViewClient);
mWebView.addJavascriptInterface(new JavascriptPostIntercept(webViewClient), "interception");
like image 150
hly Avatar answered Oct 17 '22 07:10

hly


Override shouldInterceptRequest(WebView view, WebResourceRequest request) method of WebViewClient.

e.g.

@Override
public WebResourceResponse (WebView view, WebResourceRequest request) {
    Log.i("shouldInterceptRequest", "method:" + request.method)
}
like image 27
Twisted Lullaby Avatar answered Oct 17 '22 07:10

Twisted Lullaby