Ajax POST requests loosing payload in sencha app + phonegap - ios

I'm developing a sencha web application with sencha touch 2.1.x
This app needs to run on a web server and as well as an iOS app, packaged with phonegap 3.1.
The web server version works well, but I'm facing some problems in the iOS version, when executing Ajax POST requests. This is a sample code:
var jsonParams =
{
"username": loginParams.user,
"password": loginParams.pwd,
"serverVersion": serverVersion
};
var jsonStr = JSON.stringify(jsonParams);
console.log(jsonStr);
Ext.Ajax.request({
url: internalRoute.LOGIN,
headers: {'Content-Type':'application/json'},
method: 'POST',
scope:this,
params: jsonStr,
success: function(response){
.....
},
failure: function(response) {
.....
},
});
Sometimes this requests works fine from the iOS version packaged with phonegap, but randomly it fails, because the post payload is empty. The console.log(jsonStr) prints the correct data, but the server receives no data. I also used an HTTP sniffer to capture the sent package, and it contains no POST payload.
Changed the code to user jQuery $.ajaxinstead of Ext.Ajax.request, and the problem persists.
Any idea of what can be wrong?
Thx

Looks like it's actually a proxy issue, nothing to do with sencha or phonegap.
If I deactivate the proxy, I don't get other external resources, but this issue never happens.
Will search how to fix the proxy issue.
Thanks

Related

Firebase dynamic link triggers browser open on first app launch (react native / iOS)

After first app launch/install the app triggers a Firebase dynamic link and opens the browser with this url:
...mypage.page.link//google/link/?request_ip_version=ip_version_here&match_message=No%20pre%2Dinstall%20link%20matched%20for%20this%20device%2E
I'm handling the dynamic links in the app using:
... dynamicLinks().getInitialLink().then((link) => {
handleDynamicLink(link);
});
and
const unsubscribe = dynamicLinks().onLink(handleDynamicLink);
and
Linking.addEventListener("url", (url) => {
// Logic here
});
But the browser opening seems to happen before any of those are triggered. Do I have to do anything in the native iOS code to handle this before to continue initializing the app instead of triggering the browser to open?
Thanks a lot!

iOS simulator running Capacitor converted web app can't seem to retrieve data consistently from local development server

I have a web app developed in node.js, and now I am starting to create a mobile app from it using capacitorjs. In the web app I used handlebars to parameterize views and then served them using res.render(). With capacitorjs, it seems that the way to proceed is to precompile the views (templates and partials), and just make AJAX calls to the server to get the data and then create html using Handlebars.template.view(data), etc. So far so good!
For the development phase I have the api server running on the local machine. I had been using a self-signed SSL certificate on the local machine, and it had given me no trouble for the past few months, after having previously added my own Certificate Authority's certificate to the keychain on my MacOS machine, and after accepting the development server's self-signed certificate in the browsers. With capacitorjs, after having organized web assets in a www directly and creating an index.html file, I started the process of creating the mobile app with iOS using:
npx cap add iOS
open ios/App/App.xcworkspace
I found that the iOS simulator does not like to access anything from an https server with a self-signed certificate despite the fact that I added my certificate authority's certificate to the device's Settings->General->About->Certificate Trust Settings and enabled full trust for root certificates (a list that includes my certificate authority's certificate). After struggling with this for a while, I decided to run my development server as http, at least initially to get the ball rolling. It still did not work, and I figured it is because of CORS, so I added this middleware to my app stack:
import cors from 'cors';
var corsOptions = {
origin: 'capacitor://localhost',
optionsSuccessStatus: 200
}
app.use(cors(corsOptions));
This seems to work, although fleetingly! Here's a simple AJAX request I make to test whether I can retrieve the data from the development server:
document.getElementById('test').addEventListener('click', event => {
console.log('test clicked');
console.log(`apiServer: ${apiServer}`);
$.ajax({
url: `${apiServer}/api/test`,
type: 'get',
data: {},
success: function (data) {
console.log(`/api/test`, data)
},
error: function (err) {
console.log(`error: `, err);
}
});
});
Over on the server, the route looks like this:
router.get('/api/test', function(req, res, next) {
res.send({
title: 'API Test',
apiResponse: 'success',
});
});
After starting the iOS simulator, I get my app's home screen with the "test" button. When I click it the first time, it works fine. The log shows this:
⚡️ [log] - apiServer: http://192.168.1.101:3000
⚡️ [log] - /api/test {"title":"API Test","apiResponse":"success"}
Subsequent clicks, however, give an error:
⚡️ [log] - apiServer: http://192.168.1.101:3000
⚡️ [log] - error: {"readyState":0,"status":0,"statusText":"error"}
I am not sure why. I added a second API test route and hit that on the second click, and still get the same error. That is, the first GET request works, subsequent ones don't. Over on the server I can see that it responds with a status 200 for the first GET request, and sometimes also for the second GET request (whether I hit the same test route or two different routes), however, on the iOS simulator only the first hit gets the data, the second results in error. Subsequent GET requests (third, fourth, . . ) do not get registered by the server, and the simulator continues to give the same error:
⚡️ [log] - apiServer: http://192.168.1.101:3000
⚡️ [log] - error: {"readyState":0,"status":0,"statusText":"error"}
I am stuck, and could use help. Thanks for reading!
Update: I have tried various settings for Application Transport Security as recommended in various discussions on Stack Overflow and Apple Developer Forum, including:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key><true/>
</dict>
And, various combinations of these settings:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key><true/>
<key>NSAllowsArbitraryLoadsInWebContent</key><true/>
<key>NSAllowsLocalNetworking</key><true/>
<key>NSExceptionDomains</key>
<dict>
<key>192.168.1.101:3000</key>
<dict>
<key>NSIncludesSubdomains</key><true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key<true/>
<key>NSExceptionRequiresForwardSecrecy</key><true/>
</dict>
</dict>
</dict>
But nothing seems to help. Surprisingly, if I set NSAllowsArbitraryLoads to NO, and remove all other keys in ATS, the behaviour remains the same. That is, the first AJAX request is successful, while subsequent ones are not and give the same error as earlier. ATS settings in Info.plist don't seem to matter!
It seems like this wasn't an issue of permissions to access an external API server. I wrapped up the AJAX call within a function, makeRequest(), and just tried to execute it repeatedly using setInterval():
setInterval(() => { makeRequest(); }, 2000);
This worked: repeated GET requests to the API (whether on my local server at http://192.168.1.101:3000 or on an externally available public server such as https://emojihub.herokuapp.com/api/random) are now successful. So, something seemed to have been interfering with the AJAX requests when the button is clicked: never the first time when the simulator loads the app, but subsequent times. I then added event.preventDefault() to the top of the button event listener, and this has resolved the problem.

React and Axios GET request issue with Safari on MacOs and iOs

I'm trying to do an API request using Axios, it works in every windows' and Android browsers but does not work on MacOs Safari (but in Chrome it works fine) or any iOs browser.
In the same code I make another calls to the same API (different endpoints) and it works with no problems at all in safari and iOs.
When I console.log the throwed exception turns out that's a Network error.
I don't think that's a CORS issue, couse it works on another browsers.
My request:
try {
const response = await api.get(
"/precos/get",
{
headers: {
'Content-Type': 'application/json'
'token': getToken()
}
}
);
this.filtraProdutoPorTabela(response.data.data);
} catch (err){
// do something with the error
}
Console error:
Network Error
{"url":"http://url/precos/get","method":"get","headers":{"Accept":"application/json, text/plain, /","this.state-Type":"application/json","token”:”e…c”},”baseURL”:”the base url ”,”transformRequest":[null],"transformResponse":[null],"timeout":0,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","maxContentLength":-1,"httpsAgent":{}}}
The only problem that would cause this that I can think of is that you for sure have the links on your computer set to for example: http://localhost:5000/api/posts
And that works fine since your doing it in the same machine but when you try it on your mobile devices or any other device when the browser tries to hit that route it sees the localhost portion of the url and it points to it self not your actual machine.
To solve this problem you have to put the ip address and the port of your machine not the literal text "localhost".
From:
http://localhost:5000/api/posts
To:
http://192.168.1.23:500/api/posts
http://{ YOUR IP ADDRESS }:5000/api/posts
When investigating this issue on my own I came across this post:
link not working in Safari.
For some reason on Safari link event is not being triggered. I had my onClick action, that was triggering axios call, bind to html <a /> tag. Safari was not letting axios execute request properly.
Adding:
event.preventDefault()
to function called by tag when clicked solved the issue.

POST http calls not working in Ionic iOS build

I've made an application in Ionic V4 and then build the same using cordova plugin (not capacitor). First page of my application is login where I'm getting values from form fields and sending it to login method where I am making a POST call to server.
loginUrl = 'http://localhost:3000/login';
errorLog: any;
login(form) {
const user = form.values;
this.httpClient.post(this.loginUrl, user).subscribe( response => {
this.toastController.create({message:'Login Successful', duration: 1000}).then(toast=> toast.present());
}, error => {
this.errorLog = error;
this.toastController.create({message:'Some Error Occured', duration: 1000}).then(toast=> toast.present());
})
}
Also I'm printing that error log in login page because once we make build, its hard to debug in device using Android Studio or Xcode.
So I'm printing error log like this
<h3>{{errorLog | json}}</h3>
I'm not getting error from POST call in case of running the application in web browser as well as in android. Getting error in iOS when I tried to make build and using Xcode, deployed into my iPad.
It's working fine in GET HTTP calls because previously I've tested GET HTTP calls in same but not working in POST HTTP calls.
Its returning 500 internal server error. Error object looks like
{
"statusText": "OK",
"status": 500,
"url": "http://localhost:3000/login",
"ok": false,
"name": 'HttpErrorResponse',
"message": "Http failure response for http://localhost:3000/login: 500 OK",
...
}
How I make build is
ionic build --prod --release
ionic cordova platform remove ios (if platform already exist).
ionic cordova platform add ios
ionic cordova prepare ios
Then I open the same ios folder into Xcode, select the developer account, connect my iPad and run it.
Were you able to resolve it?
I faced similar situation and here's how I got around it.
In capacitor.config.json file we need to specify 'server' from where we are getting the Api data.
"appId": "com.yoursite",
"appName": "Your Site",
"bundledWebRuntime": false,
"npmClient": "npm",
"webDir": "www",
"cordova": {},
//This part mentioned below is important.
"server": {
"url": "https://yoursite.com",
"allowNavigation": ["yoursite.com", "*.yoursite.com"]
},
Hope this helps.

Using Firebase Authentication from iOS 7.1.2 Safari

I see this error:
Error: This operation is not supported in the environment this
application is running on. "location.protocol" must be http, https or
chrome-extension and web storage must be enabled.
When I use:
firebase.auth().signInWithPopup(provider)
.then(function(result) {
console.log(result);
})
.catch(function(error) {
console.log('popup', error);
//webSettings.setDomStorageEnabled(true);
firebase.auth().signInWithRedirect(provider)
.then(function(result) {
console.log(result);
})
.catch(function(error) {
console.log('redirect', error);
firebase.auth().signInAnonymously().catch(function(error) {
console.log('anonymous', error);
});
});
});
The first two login attempts via popup and redirect fail. It seems to happen only on iOS Safari.
I see others reporting the issue with Cordova, but I don't see an answer and I'm only using web and firebase. Not Cordova or ionic etc.
The anonymous login works on iOS but that is only a test and not what we want to use to use.
If you want to test it you can use https://meetup-reporter.firebaseapp.com/ from Safari on iOS
An example dump of the error object from the returned Promise is:
{"code": "auth/operation-not-supported-in-this-environment",
"constructor": function (a, b)
{this.code="auth/"+a;this.message=b||Xf[a]||"";}, "F": function ()
{return{code:this.code,message:this.message}}, "line": 44, "message":
"This operation is not supported in the environment this application
is running on. \"location.protocol\" must be http, https or
chrome-extension and web storage must be enabled.", "sourceURL":
"https://meetup-reporter.firebaseapp.com//firebase/4.1.2/firebase-auth.js",
"stack":
"https://meetup-reporter.firebaseapp.com//firebase/4.1.2/firebase-auth.js:44:638\nhttps://meetup-reporter.firebaseapp.com//firebase/4.1.2/firebase-auth.js:45:258\nA#https://meetup-reporter.firebaseapp.com//firebase/4.1.2/firebase-auth.js:44:545\nD#https://meetup-reporter.firebaseapp.com//firebase/4.1.2/firebase-auth.js:45:242\nsignInWithPopup#https://meetup-reporter.firebaseapp.com//firebase/4.1.2/firebase-auth.js:241:48\na#https://meetup-reporter.firebaseapp.com/__/firebase/4.1.2/firebase-auth.js:260:432\nhttps://meetup-reporter.firebaseapp.com/scripts/main.js:430:36",
"toJSON": function () {var
a=Array.prototype.slice.call(arguments);a:{var
e=Array.prototype.slice.call(a);var l=0;for(var
n=!1,C=0;Cl||l>=fk.length)throw new N("internal-error","Argument
validator received an unsupported number of arguments.");e=fk[l]+"
argument "+(e.name?'"'+e.name+'" ':"")+"must be "+e.N+".";break
a}e=null}}if(e)throw new N("argument-error",d+" failed: "+e);return
b.apply(this,a);}}
signInWithRedirect actually works in Cordova now: https://firebase.google.com/docs/auth/web/cordova
signInWithPopup and signInWithRedirect should also work for iOS7 and up. I just tested both on an iOS 7 device and they both work. What you are experiencing is likely to the fact that you are using this operation in Safari Private/Incognito mode where web storage is disabled. These operations depend on web storage in order to securely communicate the OAuth result to the parent page. You will need to ask your users to switch to regular mode when this happens, or you can use the Google Sign-in JS SDk to get the OAuth credential and then signInWithCredential. I think it may work in incognito mode.

Resources