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();