| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 | var http   = require('http'),    https  = require('https'),    common = require('../common');/*! * Array of passes. * * A `pass` is just a function that is executed on `req, socket, options` * so that you can easily add new checks while still keeping the base * flexible. *//* * Websockets Passes * */module.exports = {  /**   * WebSocket requests must have the `GET` method and   * the `upgrade:websocket` header   *   * @param {ClientRequest} Req Request object   * @param {Socket} Websocket   *   * @api private   */  checkMethodAndHeader : function checkMethodAndHeader(req, socket) {    if (req.method !== 'GET' || !req.headers.upgrade) {      socket.destroy();      return true;    }    if (req.headers.upgrade.toLowerCase() !== 'websocket') {      socket.destroy();      return true;    }  },  /**   * Sets `x-forwarded-*` headers if specified in config.   *   * @param {ClientRequest} Req Request object   * @param {Socket} Websocket   * @param {Object} Options Config object passed to the proxy   *   * @api private   */  XHeaders : function XHeaders(req, socket, options) {    if(!options.xfwd) return;    var values = {      for  : req.connection.remoteAddress || req.socket.remoteAddress,      port : common.getPort(req),      proto: common.hasEncryptedConnection(req) ? 'wss' : 'ws'    };    ['for', 'port', 'proto'].forEach(function(header) {      req.headers['x-forwarded-' + header] =        (req.headers['x-forwarded-' + header] || '') +        (req.headers['x-forwarded-' + header] ? ',' : '') +        values[header];    });  },  /**   * Does the actual proxying. Make the request and upgrade it   * send the Switching Protocols request and pipe the sockets.   *   * @param {ClientRequest} Req Request object   * @param {Socket} Websocket   * @param {Object} Options Config object passed to the proxy   *   * @api private   */  stream : function stream(req, socket, options, head, server, clb) {    var createHttpHeader = function(line, headers) {      return Object.keys(headers).reduce(function (head, key) {        var value = headers[key];        if (!Array.isArray(value)) {          head.push(key + ': ' + value);          return head;        }        for (var i = 0; i < value.length; i++) {          head.push(key + ': ' + value[i]);        }        return head;      }, [line])      .join('\r\n') + '\r\n\r\n';    }    common.setupSocket(socket);    if (head && head.length) socket.unshift(head);    var proxyReq = (common.isSSL.test(options.target.protocol) ? https : http).request(      common.setupOutgoing(options.ssl || {}, options, req)    );    // Enable developers to modify the proxyReq before headers are sent    if (server) { server.emit('proxyReqWs', proxyReq, req, socket, options, head); }    // Error Handler    proxyReq.on('error', onOutgoingError);    proxyReq.on('response', function (res) {      // if upgrade event isn't going to happen, close the socket      if (!res.upgrade) {        socket.write(createHttpHeader('HTTP/' + res.httpVersion + ' ' + res.statusCode + ' ' + res.statusMessage, res.headers));        res.pipe(socket);      }    });    proxyReq.on('upgrade', function(proxyRes, proxySocket, proxyHead) {      proxySocket.on('error', onOutgoingError);      // Allow us to listen when the websocket has completed      proxySocket.on('end', function () {        server.emit('close', proxyRes, proxySocket, proxyHead);      });      // The pipe below will end proxySocket if socket closes cleanly, but not      // if it errors (eg, vanishes from the net and starts returning      // EHOSTUNREACH). We need to do that explicitly.      socket.on('error', function () {        proxySocket.end();      });      common.setupSocket(proxySocket);      if (proxyHead && proxyHead.length) proxySocket.unshift(proxyHead);      //      // Remark: Handle writing the headers to the socket when switching protocols      // Also handles when a header is an array      //      socket.write(createHttpHeader('HTTP/1.1 101 Switching Protocols', proxyRes.headers));      proxySocket.pipe(socket).pipe(proxySocket);      server.emit('open', proxySocket);      server.emit('proxySocket', proxySocket);  //DEPRECATED.    });    return proxyReq.end(); // XXX: CHECK IF THIS IS THIS CORRECT    function onOutgoingError(err) {      if (clb) {        clb(err, req, socket);      } else {        server.emit('error', err, req, socket);      }      socket.end();    }  }};
 |