3

I am having issues with making an ExtJS AJAX request to the Nodejs server between two different domains within our network and will appreciate any help. Response fails when attempting from both http and https from ExtJS client side but a Curl from my local via http returns 200 OK with proper data. We are working with content type application/json.

ExtJS onReady function has enabled CORS:

Ext.onReady(function () {
   Ext.Ajax.cors = true;
   Ext.Ajax.useDefaultXhrHeader = false;
   ... (code removed) 
})

A test from my ExtJS client side on a known working URL that will properly create the ExtJS datastore (brings back 200 OK):

Ext.create('Ext.data.Store', {
    id         : 'countryStore',
    model      : 'country',
    autoLoad   : true,
    autoDestroy: true,
    proxy: {
        type: 'rest',
        url : 'https://restcountries.eu/rest/v1/all',
        },
        reader: {
            type           : 'json',
            headers: {'Accept': 'application/json'},
            totalProperty  : 'total',
            successProperty: 'success',
            messageProperty: 'message'
        }
});

However, when attempting a request to our Nodejs server via

http:

Ext.create('Ext.data.Store', {
    id         : 'circuits',
    model      : 'circuit',
    autoLoad   : true,
    autoDestroy: true,
    proxy: {
        type: 'rest',
        url : 'http://ourNodeJsServerDomain:5500/v3/circuits',
        },
        reader: {
            type           : 'json',
            headers: {'Accept': 'application/json'},
            totalProperty  : 'total',
            successProperty: 'success',
            messageProperty: 'message'
        }
});

returns the following in Chrome's console:

Mixed Content: The page at 'https://ourExtJsDevClientSide' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://ourNodeJsServerDomain:5500/v3/circuits?_dc=1430149427032&page=1&start=0&limit=50'. This request has been blocked; the content must be served over HTTPS.

Now, when attempted over https:

Firefox shows:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://ourNodeJsServerDomain:5500/v3/circuits?_dc=1430151516741&page=1&start=0&limit=50. This can be fixed by moving the resource to the same domain or enabling CORS.

and the Request Header doesn't show "application/json", is this an issue?:

Accept  
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding 
gzip, deflate
Accept-Language 
en-US,en;q=0.5
Host    
ourNodeJsServerDomain:5500
Origin  
https://ourExtJsDevClientSide
Referer 
https://ourExtJsDevClientSide
User-Agent  
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:37.0) Gecko/20100101 Firefox/37.0

I then tried with Curl to see what the responses were to help debug

on http gives a 200 OK response but Access-Control-Allow-Origin is undefined even when we are defining it as "*":

curl http://ourNodeJsServerDomain:5500/v3circuits?_limit=1 -v
> GET /v3/circuits?_limit=1 HTTP/1.1
> User-Agent: curl/7.37.1
> Host: ourNodeJsServerDomain:5500
> Accept: */*
> 
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Access-Control-Allow-Origin: undefined
< Access-Control-Allow-Methods: GET
< Access-Control-Allow-Headers: Content-Type
< Content-Type: application/json; charset=utf-8
< Content-Length: 1126
< ETag: W/"MlbRIlFPCV6w7+PmPoVYiA=="
< Date: Mon, 27 Apr 2015 16:24:18 GMT
< Connection: keep-alive
< 
[
  { *good json data returned here* } ]

then when I attempt to Curl via https

curl https://ourNodeJsServerDomain:5500/v3/circuits?_limit=1 -v
* Server aborted the SSL handshake
* Closing connection 0
curl: (35) Server aborted the SSL handshake

We have enabled CORS on our Nodejs server:

router
    .all('*', function(req, res, next){
        res.setHeader('Content-Type', 'application/json');
        // res.setHeader("Access-Control-Allow-Origin", req.headers.origin);
        // console.log('\n\nreq.headers.origin ===================== ' + req.headers.origin);
        //I have tried allowing all * via res.SetHeader and res.header and neither is defining the Access-Control-Allow-Origin properly when curling
        //res.setHeader("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Origin", "*");
        // res.header("Access-Control-Allow-Headers", "X-Requested-With");
        res.header('Access-Control-Allow-Methods', 'GET');
        res.header('Access-Control-Allow-Headers', 'Content-Type');

I have attempted to be detailed in my thought process and I am willing to try new ways to determine how to understand and solve this.

* SOLUTION *

The issue is mixed content from the browser. Our client UI is on https (secure) whereas we were requesting http (unsecure) content from the nodejs server. We needed to allow for our nodejs server to run on https

We generated SSL certifications and implemented them onto our nodejs server.

Within the nodejs code, we enabled CORS with the CORS module and are running both http and https servers:

// enable CORS for all requests
var cors = require('cors');
app.use(cors());

// for certifications
var credentials = {
  key: fs.readFileSync('our.key'),
  cert: fs.readFileSync('our.crt')
};

var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);

httpServer.listen(port, function() {
console.log('HTTP server listening on port ' + port);
});

httpsServer.listen(httpsPort, function() {
    console.log('HTTPS server listening on port ' + httpsPort);
});
Richard
  • 826
  • 7
  • 23
  • 41
  • Have you looked at this http://stackoverflow.com/questions/27682785/sencha-extjs-cannot-send-post-request-on-cross-domain-with-ext-ajax-request – Abdul Rehman Yawar Khan Apr 28 '15 at 08:54
  • @AbdulRehmanYawarKhan I have Ext.Ajax.useDefaultXhrHeader = false; within the Ext.onReady function. The first block of example code above. Thanks. – Richard Apr 28 '15 at 14:15
  • Made any progress? I think you should first try make sure everything is properly configured in node. – Yellen Apr 28 '15 at 17:45
  • My colleague tested the call to nodejs from Advanced Rest Client (Chrome extension) and for some reason via http he is receiving Access-Control-Allow-Origin: * whereas I am receiving Access-Control-Allow-Origin: undefined. Still very mysterious. Regardless, from our ExtJs UI it is not working either way. – Richard Apr 29 '15 at 16:36
  • @Richard - tried adding Accept : application/json in the request header? – Yellen Apr 29 '15 at 21:38
  • @Seram Yes, it is located in the reader in the data.Store. Any other thoughts? – Richard Apr 30 '15 at 01:40

1 Answers1

4

There seems to be issues with both CORS and HTTPS in your server... You should try this middleware for the CORS part, and make it work when accessing the page in raw HTTP first. As far as I know, you'll have to use different ports for HTTP and HTTPS. And you will also probably need to enable CORS credentials. As I said, I think you'd better make it work in HTTP first ;)

Then, on the Ext part, as already mentioned in comments, you should probably disable default headers (or you'll have to make all of them accepted by your server; see the first comment to this answer). But you need to do that on the proxy, because apparently it replaces the global setting in Ext.Ajax.

So, something like this:

Ext.create('Ext.data.Store', {
    id         : 'countryStore',
    model      : 'country',
    autoLoad   : true,
    autoDestroy: true,
    proxy: {
        type: 'rest',
        url : 'https://restcountries.eu/rest/v1/all',
        useDefaultXhrHeader: false, // <= HERE
        reader: {
            type           : 'json',
            headers: {'Accept': 'application/json'},
            totalProperty  : 'total',
            successProperty: 'success',
            messageProperty: 'message'
        }
    } // <= and notice this change
});

Probably unrelated, but note that your indendation was incorrect and hid the fact that the reader option was applied to the store itself instead of the proxy (so it was ignored).

Community
  • 1
  • 1
rixo
  • 23,815
  • 4
  • 63
  • 68
  • Thanks for reaching out to help. I've made the minor changes and implemented the CORS module and the 'undefined' is now returning '*'. Do you know of a way to allow for 'mixed' content since our current page is https whereas we would prefer that our nodejs server run over http? – Richard Apr 30 '15 at 19:01
  • Also, I notice that the countries rest call that we use for testing that works https://restcountries.eu/rest/v1/all is served over https. Would you know how they did this without any type of authentication or keys on our client end? – Richard Apr 30 '15 at 19:15
  • You guided me in the right direction. It was just an issue of http vs https. I will update with solution. – Richard Apr 30 '15 at 21:21