sacheie
sacheie

Reputation: 768

Haskell WARP/WAI server fails to respond to AJAX calls from Android embedded WebView

UPDATE 3 When hitting the endpoint http://httpbin.org/user-agent, the request returns successfully. So something is wrong with my Haskell Warp+WAI application server.

Any ideas what could make a server API call work for most browsers, but not for Android WebView?


Just to clarify, I am not doing any cross-domain requests. I see hundreds of questions on here about that, but my AJAX request is to the same domain the WebView has loaded.

UPDATE 2 Instead of jQuery I used the more basic xhr method, like so:

function pingServer()
{
  var xhr = new XMLHttpRequest();
  xhr.open('get', URL + 'ping');

  // Track the state changes of the request.
  xhr.onreadystatechange = function()
  {
    var DONE = 4; // readyState 4 means the request is done.
    var OK   = 200; // status 200 is a successful return.

    if (xhr.readyState === DONE)
    {
      if (xhr.status === OK)
      {
        $('#submitDialog p').text(xhr.responseText + ' : ' + xhr.status);
      }
      else
      {
        $('#submitDialog p').text(xhr.responseText + ' : ' + xhr.status);
      }
    }
  };
  xhr.send(null);
}

Still no luck. The xhr.responseText is blank, and the xhr.status is 0.

I'm wondering if something is wrong with my server? I'm using an unusual server, the Haskell-based WARP with WAI. ...but then why does everything work fine in every other browser?


UPDATE I did some debugging and this is the error I'm getting on the AJAX call shown below (a basic 'is server up?' GET query):

error: NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://www.example.net:2753/ping'

Needless to say the exact URL (the real one I'm using, not the example) loads fine in any mobile or desktop browser - only the Android WebView has this problem!


I have a simple Android app; just a WebView that loads a remote URL (not a local resource). It works fine, except that all of my AJAX calls immediately invoke their error callback. I'm testing on a Samsung Galaxy S6, and building the app to SDK 21.

Here is what my first AJAX call (which fails) looks like; the others use the same properties:

$.ajax(
{
  url: URL + 'ping',
  cache: false,
  async: false,
  timeout: 5000,
  error: fail,
  success: transmitScore
});

Of course, transmitScore() and fail() are defined elsewhere within scope.

Here is what the setup of my WebView looks like:

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import java.util.Locale;

public class Example extends Activity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        setContentView(R.layout.main);

        WebView wv = (WebView) findViewById(R.id.webview);

        wv.setWebViewClient(new WebViewClient()
        {
            public void onPageFinished(WebView v, String s)
            {
                v.loadUrl("javascript: setLang('" +
                    Locale.getDefault().getLanguage() + "')");
            }
        });
        wv.getSettings().setJavaScriptEnabled(true);
        wv.loadUrl("http://example_url_for_privacy:2753/application");
    }
}

Any ideas what is going wrong? The AJAX calls work fine in desktop Chrome and Android Chrome.

I have seen a lot of questions on here about AJAX calls to local resource files requiring cross-domain permissions, but that's not my situation. All resources are on the remote server, and all AJAX calls go to it.

I've also tried setting my WebView to use WebChromeClient, but it made no difference. I believe nowadays it is the default for WebViews. In the AJAX calls, I've tried the four possible combinations of async and cache; none work.

Upvotes: 1

Views: 370

Answers (1)

sacheie
sacheie

Reputation: 768

It turns out the problem was that the WebView was loading the page by IP address, while the JavaScript referred to it by domain name. For all I know, it might be common sense not to do that; but the way non-WebView clients handled it OK made me rule it out early as a possible problem.

Upvotes: 1

Related Questions