socketioMEANseed/www/node_modules/http-proxy/lib/http-proxy/passes/ws-incoming.js
www/node_modules/http-proxy/lib/http-proxy/passes/ws-incoming.jsRaw
1var http = require('http'),
2 https = require('https'),
3 common = require('../common');
4
5/*!
6 * Array of passes.
7 *
8 * A `pass` is just a function that is executed on `req, socket, options`
9 * so that you can easily add new checks while still keeping the base
10 * flexible.
11 */
12
13/*
14 * Websockets Passes
15 *
16 */
17
18
19module.exports = {
20 /**
21 * WebSocket requests must have the `GET` method and
22 * the `upgrade:websocket` header
23 *
24 * @param {ClientRequest} Req Request object
25 * @param {Socket} Websocket
26 *
27 * @api private
28 */
29
30 checkMethodAndHeader : function checkMethodAndHeader(req, socket) {
31 if (req.method !== 'GET' || !req.headers.upgrade) {
32 socket.destroy();
33 return true;
34 }
35
36 if (req.headers.upgrade.toLowerCase() !== 'websocket') {
37 socket.destroy();
38 return true;
39 }
40 },
41
42 /**
43 * Sets `x-forwarded-*` headers if specified in config.
44 *
45 * @param {ClientRequest} Req Request object
46 * @param {Socket} Websocket
47 * @param {Object} Options Config object passed to the proxy
48 *
49 * @api private
50 */
51
52 XHeaders : function XHeaders(req, socket, options) {
53 if(!options.xfwd) return;
54
55 var values = {
56 for : req.connection.remoteAddress || req.socket.remoteAddress,
57 port : common.getPort(req),
58 proto: common.hasEncryptedConnection(req) ? 'wss' : 'ws'
59 };
60
61 ['for', 'port', 'proto'].forEach(function(header) {
62 req.headers['x-forwarded-' + header] =
63 (req.headers['x-forwarded-' + header] || '') +
64 (req.headers['x-forwarded-' + header] ? ',' : '') +
65 values[header];
66 });
67 },
68
69 /**
70 * Does the actual proxying. Make the request and upgrade it
71 * send the Switching Protocols request and pipe the sockets.
72 *
73 * @param {ClientRequest} Req Request object
74 * @param {Socket} Websocket
75 * @param {Object} Options Config object passed to the proxy
76 *
77 * @api private
78 */
79 stream : function stream(req, socket, options, head, server, clb) {
80 common.setupSocket(socket);
81
82 if (head && head.length) socket.unshift(head);
83
84
85 var proxyReq = (common.isSSL.test(options.target.protocol) ? https : http).request(
86 common.setupOutgoing(options.ssl || {}, options, req)
87 );
88
89 // Enable developers to modify the proxyReq before headers are sent
90 if (server) { server.emit('proxyReqWs', proxyReq, req, socket, options, head); }
91
92 // Error Handler
93 proxyReq.on('error', onOutgoingError);
94 proxyReq.on('response', function (res) {
95 // if upgrade event isn't going to happen, close the socket
96 if (!res.upgrade) socket.end();
97 });
98
99 proxyReq.on('upgrade', function(proxyRes, proxySocket, proxyHead) {
100 proxySocket.on('error', onOutgoingError);
101
102 // Allow us to listen when the websocket has completed
103 proxySocket.on('end', function () {
104 server.emit('close', proxyRes, proxySocket, proxyHead);
105 });
106
107 // The pipe below will end proxySocket if socket closes cleanly, but not
108 // if it errors (eg, vanishes from the net and starts returning
109 // EHOSTUNREACH). We need to do that explicitly.
110 socket.on('error', function () {
111 proxySocket.end();
112 });
113
114 common.setupSocket(proxySocket);
115
116 if (proxyHead && proxyHead.length) proxySocket.unshift(proxyHead);
117
118 //
119 // Remark: Handle writing the headers to the socket when switching protocols
120 // Also handles when a header is an array
121 //
122 socket.write(
123 Object.keys(proxyRes.headers).reduce(function (head, key) {
124 var value = proxyRes.headers[key];
125
126 if (!Array.isArray(value)) {
127 head.push(key + ': ' + value);
128 return head;
129 }
130
131 for (var i = 0; i < value.length; i++) {
132 head.push(key + ': ' + value[i]);
133 }
134 return head;
135 }, ['HTTP/1.1 101 Switching Protocols'])
136 .join('\r\n') + '\r\n\r\n'
137 );
138
139 proxySocket.pipe(socket).pipe(proxySocket);
140
141 server.emit('open', proxySocket);
142 server.emit('proxySocket', proxySocket); //DEPRECATED.
143 });
144
145 return proxyReq.end(); // XXX: CHECK IF THIS IS THIS CORRECT
146
147 function onOutgoingError(err) {
148 if (clb) {
149 clb(err, req, socket);
150 } else {
151 server.emit('error', err, req, socket);
152 }
153 socket.end();
154 }
155 }
156};