Apache and Nodejs cross domain ajax issue

2019-07-05 18:40发布

问题:

I am working on application in which I have used two servers hosted on same machine, one is apache which will work as basic host for serving php pages and other side nodejs for communication of rest api, whole application build upon backbone/marionette/requirejs/bootstrap.

Coming to the point, my normal pages are load from apache server like,

http://192.168.20.62/project/design.php

and I have configured my model like this,

define(['backbone'],function(Backbone){
'use strict';

return Backbone.Model.extend({
    url:"http://192.168.20.62:9847/page",
    defaults: {
        ...
    }
});

});

when I try to save model I am suffering from problem of ajax cross domain call and I am ended up with error in my save communication, following is the node/express server,

var express = require('/root/node_modules/express');


var app = express();

app.configure(function () {
    app.use(express.json());
    app.use(express.urlencoded());
    app.use(function (req, res, next) {
        res.setHeader('Access-Control-Allow-Origin', 'http://192.168.20.62:9847');
        res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
        res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
        res.setHeader('Access-Control-Allow-Credentials', true);
        next();
    });

})

app.post('/page', function(request, response){

    console.log(request.body);
    response.send(request.body);

});

app.listen(9847);

as you can see I have already written some patch in server code, but still the same, also I have added .htaccess at root level of both at

http://192.168.20.62 

and

http://192.168.20.62:9847 

with the following code,

Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"

but things are not helping in anyways, if I run chrome by disabling web security then thing are working properly.

chrome.exe --disable-web-security

Can you guys please help me to solve this puzzle, thanks in advance.

following is the error message from chrome javascript console

OPTIONS http://192.168.20.62:9847/page Origin http://192.168.20.62 is not allowed by Access-Control-Allow-Origin. jquery-2.0.3.min.js:6

XMLHttpRequest cannot load http://192.168.20.62:9847/page. Origin http://192.168.20.62 is not allowed by Access-Control-Allow-Origin. 

回答1:

Oops I figure out the problem, I have setup wrong url for white listing.

res.setHeader('Access-Control-Allow-Origin', 'http://192.168.20.62');

I have to whitelist the source URL which was generating cross domain, this was the only change have to do to make thing running.

Also this has browser version impact, when I have posted this issue, I was checking with firefox version 24.0.* and when I upgrade 25.0 it has stopped generating cross domain error surprisingly. But still Chrome giving natural cross domain error, when I read error message of chrome carefully I come to know that I have whitelisted wrong url.

XMLHttpRequest cannot load http://192.168.20.62:9847/page. The 'Access-Control-Allow-Origin' whitelists only 'http://192.168.20.62:9847'. Origin 'http://192.168.20.62' is not in the list, and is therefore not allowed access.



回答2:

If you don't have to deal with WebSockets, then place Node.js behind Apache via mod_proxy:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so

# disable use as forward proxy
ProxyRequests Off
# don't handle Via: headers - we don't care about them
ProxyVia Off
# no need to transport host name - not doing virtual hosting
ProxyPreserveHost Off

ProxyPass         /page/   http://192.168.20.62:9847/page/
ProxyPassReverse  /page/   http://192.168.20.62:9847/page/

# If you get HTTP status code 502 (Bad Gateway), maybe this could help
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1

In your web-page you can access your API with the same port as your Apache and you don't have any problems with Cross-Domain / Same-Origin-Policy.

You just have to separate your URIs now, e.g /page/ exists only in node.js app.

If you're serving REST only (no HTML/CSS/Images) via node.js, using JSONP would be another option. Here is a good+short description how to handle JSONP in Express