PDA

View Full Version : Sencha native app + rest server - Howto?



tt88
21 Aug 2013, 12:20 AM
Hi there

I've been searching the web high & low for relevant documentation & cannot find the right answers + am running into all sorts of issues on my app.

The most recent issue is I have my Ext.Ajax.request sending 2 requests, the 1st being an additional OPTIONS method. Rather than addressing this particular issue, it might be worth understanding the bigger picture & ensuring that I have the proper solution. Ultimately I am looking for the correct way forward of a native app interacting (saving & retrieving data) with a rest server living at a certain domain. I have not been able to find solutions for a native app specifically, only for a web-based app, where cross-domain policy issues are obvious.

Here is my app setup:
- sencha native app (compiled with sencha cmd, eventualy will be using phonegap)
- development / testing of the app done on safari browser
- connecting to rest services living in a different domain (to the test-based version in the browser)

So far I have discovered the following:
- I have to use jsonp
- jsonp does not allow for saving post data / objects to the server
- I can get around the above limitation by adding the request headers on the server (Access-Control-Allow-Origin: *) and using an ajax request (This causes the ajax request to send 2 requests, the 1st being the OPTIONS method)

My questions are as follows:
1. Since a native app is not located on a server, does this imply that you will always have to use jsonp to connect to rest services?
2. What is the solution for a native app to push new data / objects to the server? Ajax / jsonp / other?
3. When connecting to the rest server, will accessing of the rest services during development / testing in a browser be different from invoking them via a native app?

Any help will be much appreciated

Thanks
ttw

fmoseley
22 Aug 2013, 8:37 PM
With phonegap you can white list domains.
http://docs.phonegap.com/en/2.9.0/guide_whitelist_index.md.html#Domain

heppy
2 Sep 2013, 7:27 AM
tt88, did it wok for you?

for me it seems not working...
just to be sure, if I set up the access origin property in phonegap's config.xml then I can simply do posts and gets (perhaps through proxies) specifying a relative URL? like the following:


proxy: {
type: 'rest',
url: '/user/tokens',
reader: {
type: 'json',
successProperty: 'status'
}
}


Thanks!

tt88
3 Sep 2013, 4:36 AM
Hi Heppy

I haven't got the phonegap solution working yet (busy fixing other issues)
But what I did find is the following:
- in app.json I updated the url property to point to my server url
- used ajax calls throughout my app
Now my app seems to load fine when referencing services from a different domain
Still not sure how it works & haven't tested it extensively + finding any decent documentation on this is a struggle.

Good luck!

heppy
3 Sep 2013, 7:26 AM
The solution that I found to work - also reading around- is the following:

1. Create a Config class like this:


Ext.define('MyApp.util.Config', {
singleton: true,

config: {
// Decomment to use the remote server config
baseUrl: 'http://yourserver.com'


// Decomment to use the local server config
// baseUrl: ''
},


constructor: function(config) {
this.initConfig(config);
//this.callParent([config]);
}
});


2. Use absolute URLs for Ajax calls using the baseUrl defined above (directly using Ext Ajax lib or through proxies like the following):


proxy: {
type: 'rest',
url: MyApp.util.Config.getBaseUrl() + '/user',
reader: {
type: 'json',
rootProperty: 'response.user',
}
}


3. To have this working and avoid cross origin restrictions, include the following line in the config.xml file in your android project (whitelisting your server) as suggested by AM
fmoseley and explained in his link:


<access origin="myserverURL" />


Hope clarifies the situation for someone who will have this same doubts/issues! :)

Ciao ciao!

nattawat
8 Oct 2013, 12:36 AM
Hi,

I faced the same issue. I already added <access origin="*" /> into my config.xml but still no luck.

Here is the code for my Store.


Ext.define('App.store.Courses', { extend: 'Ext.data.Store',
requires: ['App.model.Course'],
config: {
model: 'App.model.Course'
},
proxy: {
type: 'ajax',
url: 'http://mysite.com/webservice',
pageParam: false, //to remove param "page"
startParam: false, //to remove param "start"
limitParam: false, //to remove param "limit"
noCache: false, //to remove param "_dc"
reader: {
type: 'json',
}
}
});


This code works fine when I run it on Chrome using Ripple to enable remote cross domain. But it does not work when I deploy to either an emulator or phone. Any idea?

tt88
15 Oct 2013, 10:45 PM
Hi, here is some feedback for anyone grappling with the same issue.

Here is a description of the environments:
1. Sencha packaged app living on the web (possibly using AppCache)
2. Sencha native app, either packaged using Sencha cmd / Phonegap
3. Services that live at a specific url that might differ from where the web version is hosted

Your options to connect to services via your Sencha app (using the different proxy objects):
- Ajax
- JsonP
- Rest (I have seen this used & not sure how / if it is different to Ajax)

Initially I was using jsonp, which without any other configuration allowed my app to connect to my services from anywhere. The problem is it only supports GET requests (not PUT/POST - I guess you can configure your server to allow these). Also, you need to wrap your service response into a function call, which makes things more complex.

To get the ajax proxy service working, you need to 2 things:
(1) For a native app packaged with Sencha you don't need to do anything. For an app packaged with phonegap/cordova update the config.xml. For a Sencha packaged web version update app.json (You might not be using your app in this packaged web version format. Modifying the app.json isn't required for running your app - unpackaged - from your webserver)

- For a phonegap build, update config.xml: <access origin="service.mysite.com" />
- For a packaged web version update app.json: "url": "http://service.mysite.com"

(2) Update your server response to include additional header information:


header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Headers: X-Requested-With,Content-Type,Accept,Origin');
header('Access-Control-Request-Method: GET,POST,PUT,OPTIONS');
header('Access-Control-Allow-Methods: GET,POST,PUT,OPTIONS');
header('Content-Type: application/json');


... so an example of a server response would be as follows:



header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Headers: X-Requested-With,Content-Type,Accept,Origin');
header('Access-Control-Request-Method: GET,POST,PUT,OPTIONS');
header('Access-Control-Allow-Methods: GET,POST,PUT,OPTIONS');
header('Content-Type: application/json');

$data = array('status'=>true, 'result'=>123);
echo json_encode($data);


I'm not sure of the full security implications of implementing the different headers and in the future plan to spend some time restricting / making access to the services more secure.
One thing to note is that the Sencha app makes 2 calls, the 1st is the Options call, to see what options are allowed, the 2nd is the actual server call.

- tt88

fmoseley
15 Oct 2013, 10:58 PM
Thanks for putting this together!

dwightjack
25 Nov 2013, 9:46 AM
Hi, just to clarify: with this setup URLs set in proxies could be without base URL (ie: "/users") or must be full URLs? Thanx!

axebutter
14 Jan 2014, 12:28 AM
I just wanted to say thanks for putting this together! Excellent post. I had the same question as dwightjack but I will figure it out and report back soon enough.

arnouxp
17 Feb 2014, 10:33 AM
Hi,

I have the same problem and it still doesn't work for me.

This is my store :



Ext.define("Versus.store.remote.Login", {
extend: "Ext.data.Store",
requires: [
"Ext.data.proxy.Rest"
],
config: {
storeId: "StoreRemoteLogin",
model: "Versus.model.User",
autoLoad: false,
proxy: {
type: "rest",
url: "http://preprod.santiane.fr/versusWS/user/login",
username: Ext.Loader.getConfig("proxy_username"),
password: Ext.Loader.getConfig("proxy_password"),
headers: {
key: Ext.Loader.getConfig("proxy_key")
},
appendId: false,
useDefaultXhrHeader: false,
withCredentials: true,
reader: {
type: "json",
successProperty: "status",
rootProperty: "value",
totalProperty: "total"
}
}
}


In my cordova/config.xml I have


<access origin="*" />


Any idea?