I am using Cordova's CLI to build a mobile application which consists of HTML, CSS, and JavaScript. The application is using jQuery 2.1.4, jQuery Mobile 1.4.5, and being packaged with Cordova 6.4.0. The application is being targed for Android 6.0.0 and iOS 10.1.
I have an issue where all of my ajax calls are hanging on iPhone 7 devices only. Below is am example of a type of ajax call I am trying to make.
$.ajax({
type: 'POST',
url: 'https://my.domain.com/myendpoint.php?parm=value',
beforeSend: function (request) {
request.setRequestHeader('Content-Type', 'application/json');
request.setRequestHeader('Accept', 'application/json');
request.setRequestHeader('Authorization', 'Basic ' + authstring);
}
})
I cannot make GET or POST requests to any of my endpoints, all of them just hang indefinitely. When I add a timeout of 60 seconds to the request the timeout will trigger my fail function after the 60 seconds. I have tried hitting HTTPS endpoints with App Transport Security enabled, as well as HTTP endpoints with App Transport Security disabled. No matter what I try the ajax will simply hang and never fail or complete unless I include a timeout.
I have tested the application on an iPhone 5, iPhone 5C, iPhone 6, and iPhone 6S, all of which on iOS 10.1.1. These do not hang and the ajax requests complete as expected. Even stranger, the ajax requests also work in XCode's iPhone 7 Simulator. However, all of my iPhone 7 users, as well as my iPhone 7 test device experience this issue where the ajax hangs indefinitely.
Any suggestions on how to fix this issue?
EDIT:
I was able to get it working by adding the meta tag:
<meta http-equiv="Content-Security-Policy" content="default-src * 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src * 'self' 'unsafe-inline'; script-src * 'self' 'unsafe-inline'; connect-src * https: http:">
I modified the meta default meta tag that cordova creates by adding wildcards to all of the values. I also added script-src, and connect-src to the tag. I originally tried them without wildcards but that did not fix my issue either, so I simply included the wildcards in both of those keys as well and the ajax requests started working.
EDIT 2:
As a side note for others who might be experiencing a similar issue, iOS devices will also cause ajax requests to hang indefinitely if a basic authentication header is sent with invalid credentials to an IIS server. When invalid credentials are sent, IIS servers by default are configured to send back a 401 with the HTTP header 'WWW-Authenticate'. If the device receives this header it does not pass the response back to the application layer, meaning your fail function will never fire. This appears to be a known issue with iOS and Cordova applications. A quick and dirty (albeit not ideal) way to circumvent that issue on the client side is to set the ajax request to synchronous with the ajax option 'async:false'. This will force the response to be given back to the application layer so the application can proceed forward, meaning your error function will trigger. This wont do your application any justice if all of your ajax requests require basic authorization, but it can at least help you diagnose the issue.