Anyway to set proxy setting in passportjs?

2019-02-16 23:29发布

问题:

Currently, I am using sails framework which is based on expressjs and using passportjs(http://passportjs.org/) to do yammer authentication.

I have problem when deploying my node app on server which is behind the company proxy. It cannot connect to yammer for OAuth2 authentication.

The error is as follow:

error: failed to obtain access token (Error: connect ETIMEDOUT)
    at /root/rlps/node_modules/passport-yammer/node_modules/passport-oauth/lib/passport-oauth/strategies/oauth2.js:125:38
    at /root/rlps/node_modules/passport-yammer/lib/passport-yammer/strategy.js:72:20
    at ClientRequest. (/root/rlps/node_modules/passport-yammer/node_modules/passport-oauth/node_modules/oauth/lib/oauth2.js:129:5)
    at ClientRequest.EventEmitter.emit (events.js:95:17)
    at CleartextStream.socketErrorListener (http.js:1547:9)
    at CleartextStream.EventEmitter.emit (events.js:95:17)
    at Socket.onerror (tls.js:1437:17)
    at Socket.EventEmitter.emit (events.js:117:20)
    at net.js:441:14
    at process._tickDomainCallback (node.js:459:13)

I believe it is because the proxy is blocking the way. I tried to set everything in environment value (like http_proxy and https_proxy) but seems the code does not acknowledge them and need to config it in somewhere in passportjs instead.

So, any good way to set proxy setting in passportjs or solve this proxy issue in nodejs?

回答1:

Node.js doesn't use the http_proxy and https_proxy variables by default.

You have to tweak the agent parameter for the request but since you don't have control on that library you can change globally like this:

npm i tunnel --save

create a setup_proxy.js:

var env = process.env;

if (!env['http_proxy']) return;

var localUrls = [
  'http://some-internal-url.mycompany.local',
];

var url    = require('url');
var tunnel = require('tunnel');
var proxy = url.parse(env['http_proxy']);

var tunnelingAgent = tunnel.httpsOverHttp({
  proxy: {
    host: proxy.hostname,
    port: proxy.port
  }
});

var https = require('https');
var http = require('http');

var oldhttpsreq = https.request;
https.request = function (options, callback) {

  if (localUrls.some(function (u) {
    return ~u.indexOf(options.host);
  })){
    return oldhttpsreq.apply(https, arguments);
  }

  options.agent = tunnelingAgent;
  return oldhttpsreq.call(null, options, callback);
};

var oldhttpreq = http.request;
http.request = function (options, callback) {

  if (localUrls.some(function (u) {
    return ~u.indexOf(options.host);
  })){
    return oldhttpreq.apply(http, arguments);
  }

  options.agent = tunnelingAgent;
  return oldhttpreq.call(null, options, callback);
};

require this at the very beginning require('./setup_proxy').

Notice that this use the same http_proxy env variable for http and https traffic, but the code is easy to follow if you need to change.