6
votes

What I am trying to do:

Proxy a java api that runs on https://127.0.0.1:443/api/ along side my UI that runs on non-SSL http://127.0.0.1:1337/ in order to circumnavigate some CORS issues.

My attempt:

  1. Proxy the api at the SSL port 443 to my non-SSL development port of 1338.
  2. proxy my UI to 1337
  3. Proxy 1137 to :8080/index.html and proxy 1338 to :8080/api/
  4. Access my app from localhost:8080

My problem:

The UI comes in just fine... but I can not hit the API at :8080/api/httpSession/init

Yes, I can still hit the API at https://localhost/api/httpSession/init

api.js - Renders index.html at :1337

var app = express();

app.all('*', function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});

var options = {
  changeOrigin: true,
  target: {
      https: true
  }
};

httpProxy.createServer(443, '127.0.0.1', options).listen(1338);

start.js - Proxies 1337 and 1338 into 8080

// First I start my two servers
uiServer.start(); // renders index.html at 1337
apiServer.start(); // 

// I attempt to patch them back into one single non-SSL port.
app
  .use('/', proxy({target: 'http://localhost:1337/'}))
  .all('/api/*', proxy({target: 'http://localhost:1338/'}))
  .listen(8080, function () {
    console.log('PROXY SERVER listening at http://localhost:%s', 8080);
  });
2
I would recommend you use nginx as a reverse proxy to achieve what you need. Here are some instructions to achieve something similar to what you need. This should also help... - mkhanoyan
Is there a reason you're proxying your api twice? First to port 1338, then to port 8080 at /api/? - kevin.groat
I know this is off topic but you could also use a web server with reverse proxy to achieve this on the same port. For example, you could use IIS or Nginx with to seperate reverse proxy endpoints on one virtual server. - Mathieu de Lorimier

2 Answers

2
votes

What you're looking for is request piping. Try this example:

  // Make sure request is in your package.json
  //   if not, npm install --save request
  var request = require('request');

  // Intercept all routes to /api/...
  app.all('/api/*', function (req, res) {
    // Get the original url, it's a fully qualified path
    var apiPath = req.originalUrl;

    // Form the proxied URL to your java API
    var url = 'https://127.0.0.1' + apiPath;

    // Fire off the request, and pipe the response
    // to the res handler
    request.get(url).pipe(res);
  });

Make sure to add some error handling if the api can't be reached, such as this SO solution.

1
votes

For the proxy issue, my guess is that it is keeping the /api/* in the url and that's not present on the router in your API service. You could try adding /api to the router in the API service since it's going to keep the url string the same when it sends it. Otherwise, you likely need to proxy and rewrite the url so that the API will match the request to a route.

On another note, what about just installing the cors module and using in the app? I do something similar and it's working well without all the proxy items. https://www.npmjs.com/package/cors