1

I am using ember 1.5 using grunt-cli and wanted to happen ajax call for CORS support using dataType: "JSON".

Ember.$.ajax({
    type: "GET",
    url: App.serverURL + 'logVisit', // callback for jsonP
    data : {
        'fp': App.fp
    },
    dataType : "JSON",
    success: function(response) {
        console.log('DEBUG: visitor has been registered');
    },
    error: function(jqXHR, textStatus, errorThrown) {
        console.log("DEBUG jqXHR.responseText : ",jqXHR.responseText);
        var response = jqXHR.responseText;

        console.log('Failure!');
        if(jqXHR.status&&jqXHR.status==400){
            // alert(jqXHR.responseText);
            var response = $.parseJSON(jqXHR.responseText);

            if (response) {
                console.log(response.error);
            } else {
                // This would mean an invalid response from the server - maybe the site went down or whatever...
                console.log("DEBUG: Inside jqXHR.status : Something went wrong");
            }
        } else {
            console.log("DEBUG: Something went wrong");
        }
    }
});

on IE10/11 its running good. But on IE8/9, as it requires XDR object, its did not work and showing console as

LOG: DEBUG jqXHR.responseText : undefined
LOG: Failure! 
LOG: DEBUG: Something went wrong

Any help or hack?

My Request Header:

Accept:application/json, text/javascript, */*; q=0.01
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Host:localhost:8080
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36

Response headers in non IE 8/9 browsers

Access-Control-Allow-Origin:*
Content-Type:application/json
Date:Wed, 25 Mar 2015 16:01:56 GMT
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
Sumit Ramteke
  • 1,487
  • 1
  • 16
  • 39
  • What is the value of `jqXHR.responseText`? That is, instead of attempting to parse it as json with `parseJSON`, just echo it to console (`console.log(jqXHR.responseText);`). – lsowen Mar 25 '15 at 12:31
  • getting response as `undefined` – Sumit Ramteke Mar 25 '15 at 12:39
  • "on IE10/11 its running good but because of XDR, its not working properly" — this doesn't make sense. It can't be running good and not working properly at the same time. Also IE10/11 don't need XDR, that's for very old versions of IE. – Quentin Mar 25 '15 at 12:58
  • sorry with my English typo. what my point is, my application only supports `XMLHttpRequest` and not `XDR`. Hence, facing problem with IE8/9. I hope that answers your doubt. – Sumit Ramteke Mar 25 '15 at 15:56

2 Answers2

2

I found my answer in support of @Isowen's reply.

I have added this piece of code before window.App = Ember.Application.create({}); to support XDR for IE8/9

Ember.$.ajaxTransport( function( options, originalOptions, jqXHR ) {
  var xdr;

  return {
    send: function( _, completeCallback ) {
      xdr = new XDomainRequest();
      xdr.onload = function() {
        if (xdr.contentType.match(/\/json/)) {
          options.dataTypes.push("json");
        }

        completeCallback(200, 'success', { text: xdr.responseText } );
      };
      xdr.onerror = xdr.ontimeout = function() {
        completeCallback(400, 'failed', { text: xdr.responseText } );
      }

      xdr.open(options.type, options.url);
      xdr.send(options.data);
    },
    abort: function() {
      if(xdr) {
        xdr.abort();
      }
    }
  };
});

and as per @Isowen's suggestion, while doing ajax request

Ember.$.ajax({
    type: "GET",
    url: App.serverURL + 'logVisit',
    data : {
        'fp': App.fp
    },
    dataType : "JSON",
    xhrFields: {withCredentials: true}, // line added
    ....
});

People who are handling request with REST adapters can use

App.ApplicationAdapter = DS.RESTAdapter.extend({
    host: App.host,
    namespace : App.namespace,
    ajax: function(url, method, hash) {
        hash = hash || {}; // hash may be undefined
        hash.crossDomain = true;
        hash.xhrFields = { // import line added
            withCredentials: true    // import line added       
        };
        console.log('DEBUG: inside RESTAdapter ajax call');
        return this._super(url, method, hash);
    }
});

and in the backend (here Spring - Java)

@Component("corsFilter")
public class CORSResponseFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

            response.addHeader("Access-Control-Allow-Origin", "http://YOUR-LINK"); // IMPORT LINE ADDED
            response.addHeader("Access-Control-Allow-Credentials", "true"); // IMPORT LINE ADDED
            if (request.getHeader("Access-Control-Request-Method") != null
                && "OPTIONS".equals(request.getMethod())) {
            // CORS "pre-flight" request
            response.addHeader("Access-Control-Allow-Methods",
                    "GET, POST, PUT, DELETE");
            response.addHeader("Access-Control-Allow-Headers",
                    "X-Requested-With,Origin,Content-Type, Accept");
        }
        filterChain.doFilter(request, response);
    }
}

Thanks @Isowen for your help.

Sumit Ramteke
  • 1,487
  • 1
  • 16
  • 39
0

It looks like you are missing setting the xhrFields.withCredentials field to true.(Not required for all CORS requests, and only partially supported in IE10).

Make sure your server is returning the Access-Control-Allow-Origin header, and that the value matches your request origin.

It is likely something is wrong with the server side CORS implementation. A slightly edited implementation of your code on jsfiddle which runs against httpbin.org appears to work correctly in Firefox, Chrome, and IE11: http://jsfiddle.net/n94w774n/.

EDIT:

Since the Origin and Host are both localhost (just different ports), there are two things you need to check the Security Zone settings for localhost: Access denied in IE 10 and 11 when ajax target is localhost

Community
  • 1
  • 1
lsowen
  • 3,728
  • 1
  • 21
  • 23
  • The documentation says that `xhrFields.withCredentials` causes it to send cookies. I don't see what that has to do with using the XDR instead of the XHR object in old versions of IE. The code, clearly, is already setting `Access-Control-Allow-Origin` correctly or it wouldn't work in modern browsers. – Quentin Mar 25 '15 at 12:57
  • @Quentin : I have provided with my Request Headers. Hope that helps – Sumit Ramteke Mar 25 '15 at 16:13
  • @Isowen : I have provided with my Response Header. Let me know if have to add some more params with it. – Sumit Ramteke Mar 25 '15 at 16:19
  • @sumitramteke are you sure IE 10/ IE11 are adding the `Origin` header? Will your server application throw an `HTTP 400` if that header is missing? It appears that IE 10 and IE 11 don't consider port numbers, so `localhost:9000` and `localhost:8080` will be the same host, so they won't add the `Origin` header. – lsowen Mar 25 '15 at 16:23
  • @Isowen : yes, I tried just now on IE11. It is responding with `Access-Control-Allow-Origin:*`. Right now I cannot check with IE9, will reply you once I am available with the same. Will add request headers received by server in my question itself – Sumit Ramteke Mar 25 '15 at 16:35
  • @sumitramteke yes, but is the request from IE11 including the `Origin` header? – lsowen Mar 25 '15 at 23:07
  • @Isowen : No, neither of any browsers are included with Origin header in request. – Sumit Ramteke Mar 26 '15 at 05:32
  • @Isowen : added `Access-Control-Allow-Origin` and `Access-Control-Allow-Credentials:true` in place of `*` and as per your suggestion added `xhrFields: { withCredentials : true }` and everything start supporting – Sumit Ramteke Mar 26 '15 at 08:57
  • Please refer my answer. I hope that helps – Sumit Ramteke Mar 26 '15 at 09:27