Cross Origin resource sharing issue during touch application development


Problem Statement

There are situation where you may need to make use of an existing set of APIs exposed as REST services. Commonly seen situations are
• When you build a touch application for an existing web application (which might have been built using ExtJS or some other less popular framework)
• When you try to consume a service hosted at different site

In such cases, making an Ajax call becomes tricky and it expect you to take care of certain things to be able to actually call the hosted REST APIs. It is possible that the existing APIs hosted in certain domain may not have been designed to work in an environment which will support cross origin resource sharing (CORS). Even if it is designed for resource sharing you need to be aware of certain header information that you may need to supply. For example in one of the case, we wanted to receive json object as part of REST response and by default server was returning output in XML format.

As part of this article we will talk about some of these situations.

Solution

Before we proceed with the solution, let’s take a look at the sample Ajax request that we often use:
Ext.Ajax.request({
url : BASE_REST_URL + 'logins',
params : {
BusinessUnit : 'Walking Tree',
Login : 'Login',
Password : 'password'
},

success: function( response, options ) {
if ( response.status === 200 ) {
var pnl = this.getNavigationPanel();

if ( Ext.isEmpty(pnl) ) {
pnl = Ext.create(‘AM.view.NavigationPanel’, {});
this.getAppContainer().add(pnl);
}

this.getAppContainer().setActiveItem(pnl);
pnl.setActiveItem(0);
} else {
Ext.Msg.alert( MESSAGE.FAILURE, MESSAGE.AUTHENTICATION_FAILURE_MESSAGE );
}

},
failure : function( response, options ) {
Ext.Msg.alert( MESSAGE.FAILURE, MESSAGE.AUTHENTICATION_FAILURE_MESSAGE );
},
scope:this
});

In general, you would expect this code to work for you and give the desired result. However, when you run, it may give below error:
XMLHttpRequest cannot load http://{BASE_REST_URL}/logins. Origin http://localhost:18080 is not allowed by Access-Control-Allow-Origin.

This clearly indicates that either the server doesn’t support CORS or you are not providing the appropriate parameters.

Scenario 1: When the hosted APIs are not designed for CORS but you have the flexibility to get it changed
There are simple configuration in the web.xml which enables your REST APIs to be able to share cross domain resources. Specify following filter

And apply above filter on your API and your API should be ready to serve the cross domain calls.

Scenario 2 : When the hosted APIs are designed for CORS
When the Rest APIs are already designed / configured for CORS, your job becomes a little easy. However, you still need to ensure few stuffs while making an Ajax request.

  1. Set useDefaultXhrHeader to false so that you don’t send the default Xhr header with every request
    1. This should be set to false when making CORS (cross-domain) requests.
    2. There are two ways in which you can do this
      1. Setting this at application level – you often do this by including Ext.Ajax.setUseDefaultXhrHeader(false); at the top of app.js file.
      2. Setting this at the Ajax call level – you do this by setting useDefaultXhrHeader to false
  2. Check the format in which you need to receive the response. For example – when I had to receive data in json format then I had to supply following settings for the headers
    1. ‘Content-Type’ : ‘application/x-www-form-urlencoded’,
    2. ‘Accept’ : ‘application/json’
  3. Check the methods supported by the service provider. For example same request can be rendered using GET as well as PUT. However, your provider might have just allowed that API for the put method. In such case you shall also set corresponding method in your Ajax request.
    1. method : ‘GET’,

Scenario 3 : When the service provider is not willing to change their API configuration to support CORS or when you don’t have much control on the service provider
When you cannot get the REST API configuration changed to support CORS, one of the option could be to create a wrapper function on your web server and allow that server to retrieve the data for you and fetch it to your application. For example you can make use of Servlet to call the REST API and by deploying the servlet inside your web server.
Below piece of code is what you need:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String[] httpParamsMethod = request.getParameterValues( “method” );

PrintWriter out = response.getWriter();

if ( httpParamsMethod.length == 0 ) {
throw new ServletException(“A valid method name has not been provided!”);
}

response.setContentType(“text/html”);
response.setHeader(“Cache-control”, “no-cache, no-store”);
response.setHeader(“Pragma”, “no-cache”);
response.setHeader(“Expires”, “-1”);
response.setHeader(“Access-Control-Allow-Origin”, “*”);
response.setHeader(“Access-Control-Allow-Methods”, “POST,GET,DELETE,PUT”);
response.setHeader(“Access-Control-Allow-Headers”, “origin,x-requested-with,content-type”);
response.setHeader(“Access-Control-Allow-Credentials”, “true”);

final Client c = Client.create();

WebResource webRes = c.resource( baseURL + httpParamsMethod[0] );
String result = webRes.accept(MediaType.APPLICATION_JSON_TYPE).get(String.class);
out.print(result);
out.close();
}

Once you have this proxy Servlet in place, you can call the rest APIs from your Javascript code.

Note
1) You may need to change above servlet code to pass required parameters
2) I have used jersey for consuming REST services and you need to download corresponding jar and use that in your program

Summary

As part of this article I have explained various ways in which you can overcome issues related to cross origin issue while working on Sencha Touch (or ExtJS) applications. While it boils down to minor configuration changes on the server and in the javascript, if you have two separate teams looking into two different things then it often becomes tricky. I hope this article will enable to give write suggestion to the other side of the team and sort out any issue related to cross origin quickly.

At Walking Tree we practice and recommend Sencha Products like ExtJS and Sencha Touch to build amazing web / touch apps. In case you are looking for training or professional assistance, contact us by visiting our website.

Reference

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
http://www.w3.org/TR/cors/#access-control-allow-origin-response-header
http://www.mysamplecode.com/2012/03/extjs-ajax-json-request-response.html
http://docs.sencha.com/touch/2-0/#!/api/Ext.Ajax
http://en.wikipedia.org/wiki/List_of_HTTP_headers
http://jersey.java.net/
http://docs.sencha.com/touch/2-0/#!/guide/ajax
http://www.html5rocks.com/en/tutorials/cors/

Tagged with: ,
Posted in Sencha Touch

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

We Have Moved Our Blog!

We have moved our blog to our company site. Check out https://walkingtree.tech/index.php/blog for all latest blogs.

Sencha Select Partner Sencha Training Partner
Xamarin Authorized Partner
Do More. With Sencha.

Recent Publication
%d bloggers like this: