http: add shouldUpgradeCallback to let servers control HTTP upgrades · nodejs/node@9b043a9
1+'use strict';
2+3+const common = require('../common');
4+const assert = require('assert');
5+6+const net = require('net');
7+const http = require('http');
8+9+function testUpgradeCallbackTrue() {
10+const server = http.createServer({
11+shouldUpgradeCallback: common.mustCall((req) => {
12+assert.strictEqual(req.url, '/websocket');
13+assert.strictEqual(req.headers.upgrade, 'websocket');
14+15+return true;
16+})
17+});
18+19+server.on('upgrade', function(req, socket, upgradeHead) {
20+assert.strictEqual(req.url, '/websocket');
21+assert.strictEqual(req.headers.upgrade, 'websocket');
22+assert.ok(socket instanceof net.Socket);
23+assert.ok(upgradeHead instanceof Buffer);
24+25+socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
26+'Upgrade: WebSocket\r\n' +
27+'Connection: Upgrade\r\n' +
28+'\r\n\r\n');
29+});
30+31+server.on('request', common.mustNotCall());
32+33+server.listen(0, common.mustCall(() => {
34+const req = http.request({
35+port: server.address().port,
36+path: '/websocket',
37+headers: {
38+'Upgrade': 'websocket',
39+'Connection': 'Upgrade'
40+}
41+});
42+43+req.on('upgrade', common.mustCall((res, socket, upgradeHead) => {
44+assert.strictEqual(res.statusCode, 101);
45+assert.ok(socket instanceof net.Socket);
46+assert.ok(upgradeHead instanceof Buffer);
47+socket.end();
48+server.close();
49+50+testUpgradeCallbackFalse();
51+}));
52+53+req.on('response', common.mustNotCall());
54+req.end();
55+}));
56+}
57+58+59+function testUpgradeCallbackFalse() {
60+const server = http.createServer({
61+shouldUpgradeCallback: common.mustCall(() => {
62+return false;
63+})
64+});
65+66+server.on('upgrade', common.mustNotCall());
67+68+server.on('request', common.mustCall((req, res) => {
69+res.writeHead(200, { 'Content-Type': 'text/plain' });
70+res.write('received but not upgraded');
71+res.end();
72+}));
73+74+server.listen(0, common.mustCall(() => {
75+const req = http.request({
76+port: server.address().port,
77+path: '/websocket',
78+headers: {
79+'Upgrade': 'websocket',
80+'Connection': 'Upgrade'
81+}
82+});
83+84+req.on('upgrade', common.mustNotCall());
85+86+req.on('response', common.mustCall((res) => {
87+assert.strictEqual(res.statusCode, 200);
88+let data = '';
89+res.on('data', (chunk) => { data += chunk; });
90+res.on('end', common.mustCall(() => {
91+assert.strictEqual(data, 'received but not upgraded');
92+server.close();
93+94+testUpgradeCallbackTrueWithoutHandler();
95+}));
96+}));
97+req.end();
98+}));
99+}
100+101+102+function testUpgradeCallbackTrueWithoutHandler() {
103+const server = http.createServer({
104+shouldUpgradeCallback: common.mustCall(() => {
105+return true;
106+})
107+});
108+109+// N.b: no 'upgrade' handler
110+server.on('request', common.mustNotCall());
111+112+server.listen(0, common.mustCall(() => {
113+const req = http.request({
114+port: server.address().port,
115+path: '/websocket',
116+headers: {
117+'Upgrade': 'websocket',
118+'Connection': 'Upgrade'
119+}
120+});
121+122+req.on('upgrade', common.mustNotCall());
123+req.on('response', common.mustNotCall());
124+125+req.on('error', common.mustCall((e) => {
126+assert.strictEqual(e.code, 'ECONNRESET');
127+server.close();
128+129+testUpgradeCallbackError();
130+}));
131+req.end();
132+}));
133+}
134+135+136+function testUpgradeCallbackError() {
137+const server = http.createServer({
138+shouldUpgradeCallback: common.mustCall(() => {
139+throw new Error('should upgrade callback failed');
140+})
141+});
142+143+server.on('upgrade', common.mustNotCall());
144+server.on('request', common.mustNotCall());
145+146+server.listen(0, common.mustCall(() => {
147+const req = http.request({
148+port: server.address().port,
149+path: '/websocket',
150+headers: {
151+'Upgrade': 'websocket',
152+'Connection': 'Upgrade'
153+}
154+});
155+156+req.on('upgrade', common.mustNotCall());
157+req.on('response', common.mustNotCall());
158+159+process.on('uncaughtException', common.mustCall(() => {
160+process.exit(0);
161+}));
162+163+req.end();
164+}));
165+}
166+167+testUpgradeCallbackTrue();