Question

I am developing a website using express.js and ember over node.

I have hosted my website in a ubuntu server and this website uses a set of webservices (which are running in some other different server). To avoid cross domain issue (while calling webservices from website), I am using http-proxy as follows

var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var httpProxy = require('http-proxy');
var endpoint  = {
    host:   'WEBSERVICES_HOSTED_IP_ADDRESS',
    port:   80,
    prefix: '/api'
}

var proxy = new httpProxy.RoutingProxy();
var app = express();

app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('xxxxx'));
app.use(express.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req, res) {
    if (req.url.indexOf(endpoint.prefix) === 0) {
        proxy.proxyRequest(req, res, endpoint);
    }
});

if ('development' == app.get('env')) {
    app.use(express.errorHandler());
}

app.get('/', routes.index);

http.createServer(app).listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
});

I have several webservices with GET method type and I was able to call all these webservices successfully from website. My AJAX code (for GET) is as follows:

        $.ajax({
            type: 'GET',
            async: false,
            url: '/api/{API_NAME}',
            success: function (data) {
               alert("success");
            },
            failure: function(error){
                alert("failure");
            }
        });

Thus the above http-proxy code handles all my webservices (with GET method type) successfully. However, I have issues in calling webservices with POST method type.

AJAX code (POST) as follows:

$.ajax({
    type: "POST",
    dataType: "json",
    url: "/api/{API_NAME}",
    data: requestData,
    async: false,
    success: function(data,status, jqXHR) {
        alert('success');
    },
    error: function (xhr, ajaxOptions   , thrownError){
        alert('failure');
    }
});

I am not retrieving any response for the webservices with POST type. If I replace the above API URL from:

url: "/api/{API_NAME}"

to

url: "http://www.apiwebsite.com/api/{API_NAME}"

I can view the API's response in browser console. However I was not able to handle this response in AJAX code. failure alert box is displayed (failure block of my AJAX code).

Console log:

 XMLHttpRequest cannot load http://www.apiwebsite.com/api/{API_NAME}. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. 

Hence I feel that, I have to write some code to handle these POST request and responses through http-proxy. Can anyone please guide me.

I found a similar issue in https://github.com/nodejitsu/node-http-proxy/issues/180. However, I am unable to make POST requests successfully.

Please Note: When I tried using 'proxy-middleware' module:

var proxyFunc = proxy(url.parse('http://www.apiwebsite.com'))
app.use(function (req, res, next) {
    if(req.url.match(/^\/api/)) { // 'yoursite.com/api' --> 'apiwebsite.com/api'
        proxyFunc(req, res, next);
    } else {  // other routes
        next();
    }
});
Was it helpful?

Solution 2

I have fixed this issue by making a small change in app setting code:

var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var httpProxy = require('http-proxy');
var endpoint  = {
    host:   'WEBSERVICES_HOSTED_IP_ADDRESS',
    port:   80,
    prefix: '/api'
}

var proxy = new httpProxy.RoutingProxy();
var app = express();

app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.methodOverride());
app.use(express.cookieParser('xxxxx'));
app.use(express.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req, res) {
    if (req.url.indexOf(endpoint.prefix) === 0) {
        proxy.proxyRequest(req, res, endpoint);
    }
});
app.use(express.bodyParser());

if ('development' == app.get('env')) {
    app.use(express.errorHandler());
}
app.get('/', routes.index);

http.createServer(app).listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
});

I have used the same code. Just moved

app.use(express.bodyParser());

below

app.use(function(req, res) {
    if (req.url.indexOf(endpoint.prefix) === 0) {
        proxy.proxyRequest(req, res, endpoint);
    }
});

Now, API with POST and GET requests are made successfully. However, I was not sure how it worked. It will be great if someone explain the reason how it worked.

Thank You.

OTHER TIPS

Use proxy-middleware like this:

var express = require('express')
, url = require('url')
, proxy = require('proxy-middleware');

var app = express();
app.use('/api', proxy(url.parse('https://damphat.com/')));
app.listen(80);

TEST THIS PROXY ON YOUR BROWER:

Edit:

var express = require('express')
, url = require('url')
, proxy = require('proxy-middleware');

var app = express();

var proxyFunc = proxy(url.parse('http://apiwebsite.com/api'))
app.use(function (req, res, next) {
    if(req.url.match(/^\/api/)) { // 'yoursite.com/api' --> 'apiwebsite.com/api'
        proxyFunc(req, res, next);
    } else {  // other routes
        next();
    }
});

app.listen(80);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top