http.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. var expect = require('chai').expect;
  2. var util = require('./util');
  3. var fs = require('fs');
  4. var path = require('path');
  5. var url = require('url');
  6. var net = require('net');
  7. var http2 = require('../lib/http');
  8. var https = require('https');
  9. var serverOptions = {
  10. key: fs.readFileSync(path.join(__dirname, '../example/localhost.key')),
  11. cert: fs.readFileSync(path.join(__dirname, '../example/localhost.crt')),
  12. rejectUnauthorized: true,
  13. log: util.serverLog
  14. };
  15. var agentOptions = {
  16. key: serverOptions.key,
  17. ca: serverOptions.cert,
  18. rejectUnauthorized: true,
  19. log: util.clientLog
  20. };
  21. var globalAgent = new http2.Agent(agentOptions);
  22. describe('http.js', function() {
  23. beforeEach(function() {
  24. http2.globalAgent = globalAgent;
  25. });
  26. describe('Server', function() {
  27. describe('new Server(options)', function() {
  28. it('should throw if called without \'plain\' or TLS options', function() {
  29. expect(function() {
  30. new http2.Server();
  31. }).to.throw(Error);
  32. expect(function() {
  33. http2.createServer(util.noop);
  34. }).to.throw(Error);
  35. });
  36. });
  37. describe('method `listen()`', function () {
  38. it('should emit `listening` event', function (done) {
  39. var server = http2.createServer(serverOptions);
  40. server.on('listening', function () {
  41. server.close();
  42. done();
  43. })
  44. server.listen(0);
  45. });
  46. it('should emit `error` on failure', function (done) {
  47. var server = http2.createServer(serverOptions);
  48. // This TCP server is used to explicitly take a port to make
  49. // server.listen() fails.
  50. var net = require('net').createServer();
  51. server.on('error', function () {
  52. net.close()
  53. done();
  54. });
  55. net.listen(0, function () {
  56. server.listen(this.address().port);
  57. });
  58. });
  59. });
  60. describe('property `timeout`', function() {
  61. it('should be a proxy for the backing HTTPS server\'s `timeout` property', function() {
  62. var server = new http2.Server(serverOptions);
  63. var backingServer = server._server;
  64. var newTimeout = 10;
  65. server.timeout = newTimeout;
  66. expect(server.timeout).to.be.equal(newTimeout);
  67. expect(backingServer.timeout).to.be.equal(newTimeout);
  68. });
  69. });
  70. describe('method `setTimeout(timeout, [callback])`', function() {
  71. it('should be a proxy for the backing HTTPS server\'s `setTimeout` method', function() {
  72. var server = new http2.Server(serverOptions);
  73. var backingServer = server._server;
  74. var newTimeout = 10;
  75. var newCallback = util.noop;
  76. backingServer.setTimeout = function(timeout, callback) {
  77. expect(timeout).to.be.equal(newTimeout);
  78. expect(callback).to.be.equal(newCallback);
  79. };
  80. server.setTimeout(newTimeout, newCallback);
  81. });
  82. });
  83. });
  84. describe('Agent', function() {
  85. describe('property `maxSockets`', function() {
  86. it('should be a proxy for the backing HTTPS agent\'s `maxSockets` property', function() {
  87. var agent = new http2.Agent({ log: util.clientLog });
  88. var backingAgent = agent._httpsAgent;
  89. var newMaxSockets = backingAgent.maxSockets + 1;
  90. agent.maxSockets = newMaxSockets;
  91. expect(agent.maxSockets).to.be.equal(newMaxSockets);
  92. expect(backingAgent.maxSockets).to.be.equal(newMaxSockets);
  93. });
  94. });
  95. describe('method `request(options, [callback])`', function() {
  96. it('should use a new agent for request-specific TLS settings', function(done) {
  97. var path = '/x';
  98. var message = 'Hello world';
  99. var server = http2.createServer(serverOptions, function(request, response) {
  100. expect(request.url).to.equal(path);
  101. response.end(message);
  102. });
  103. server.listen(1234, function() {
  104. var options = url.parse('https://localhost:1234' + path);
  105. options.key = agentOptions.key;
  106. options.ca = agentOptions.ca;
  107. options.rejectUnauthorized = true;
  108. http2.globalAgent = new http2.Agent({ log: util.clientLog });
  109. http2.get(options, function(response) {
  110. response.on('data', function(data) {
  111. expect(data.toString()).to.equal(message);
  112. server.close();
  113. done();
  114. });
  115. });
  116. });
  117. });
  118. it('should throw when trying to use with \'http\' scheme', function() {
  119. expect(function() {
  120. var agent = new http2.Agent({ log: util.clientLog });
  121. agent.request({ protocol: 'http:' });
  122. }).to.throw(Error);
  123. });
  124. });
  125. });
  126. describe('OutgoingRequest', function() {
  127. function testFallbackProxyMethod(name, originalArguments, done) {
  128. var request = new http2.OutgoingRequest();
  129. // When in HTTP/2 mode, this call should be ignored
  130. request.stream = { reset: util.noop };
  131. request[name].apply(request, originalArguments);
  132. delete request.stream;
  133. // When in fallback mode, this call should be forwarded
  134. request[name].apply(request, originalArguments);
  135. var mockFallbackRequest = { on: util.noop };
  136. mockFallbackRequest[name] = function() {
  137. expect(Array.prototype.slice.call(arguments)).to.deep.equal(originalArguments);
  138. done();
  139. };
  140. request._fallback(mockFallbackRequest);
  141. }
  142. describe('method `setNoDelay(noDelay)`', function() {
  143. it('should act as a proxy for the backing HTTPS agent\'s `setNoDelay` method', function(done) {
  144. testFallbackProxyMethod('setNoDelay', [true], done);
  145. });
  146. });
  147. describe('method `setSocketKeepAlive(enable, initialDelay)`', function() {
  148. it('should act as a proxy for the backing HTTPS agent\'s `setSocketKeepAlive` method', function(done) {
  149. testFallbackProxyMethod('setSocketKeepAlive', [true, util.random(10, 100)], done);
  150. });
  151. });
  152. describe('method `setTimeout(timeout, [callback])`', function() {
  153. it('should act as a proxy for the backing HTTPS agent\'s `setTimeout` method', function(done) {
  154. testFallbackProxyMethod('setTimeout', [util.random(10, 100), util.noop], done);
  155. });
  156. });
  157. describe('method `abort()`', function() {
  158. it('should act as a proxy for the backing HTTPS agent\'s `abort` method', function(done) {
  159. testFallbackProxyMethod('abort', [], done);
  160. });
  161. });
  162. });
  163. describe('OutgoingResponse', function() {
  164. it('should throw error when writeHead is called multiple times on it', function() {
  165. var called = false;
  166. var stream = { _log: util.log, headers: function () {
  167. if (called) {
  168. throw new Error('Should not send headers twice');
  169. } else {
  170. called = true;
  171. }
  172. }, once: util.noop };
  173. var response = new http2.OutgoingResponse(stream);
  174. response.writeHead(200);
  175. response.writeHead(404);
  176. });
  177. it('field finished should be Boolean', function(){
  178. var stream = { _log: util.log, headers: function () {}, once: util.noop };
  179. var response = new http2.OutgoingResponse(stream);
  180. expect(response.finished).to.be.a('Boolean');
  181. });
  182. it('field finished should initially be false and then go to true when response completes',function(done){
  183. var res;
  184. var server = http2.createServer(serverOptions, function(request, response) {
  185. res = response;
  186. expect(res.finished).to.be.false;
  187. response.end('HiThere');
  188. });
  189. server.listen(1236, function() {
  190. http2.get('https://localhost:1236/finished-test', function(response) {
  191. response.on('data', function(data){
  192. var sink = data; //
  193. });
  194. response.on('end',function(){
  195. expect(res.finished).to.be.true;
  196. server.close();
  197. done();
  198. });
  199. });
  200. });
  201. });
  202. });
  203. describe('test scenario', function() {
  204. describe('simple request', function() {
  205. it('should work as expected', function(done) {
  206. var path = '/x';
  207. var message = 'Hello world';
  208. var server = http2.createServer(serverOptions, function(request, response) {
  209. expect(request.url).to.equal(path);
  210. response.end(message);
  211. });
  212. server.listen(1234, function() {
  213. http2.get('https://localhost:1234' + path, function(response) {
  214. response.on('data', function(data) {
  215. expect(data.toString()).to.equal(message);
  216. server.close();
  217. done();
  218. });
  219. });
  220. });
  221. });
  222. });
  223. describe('2 simple request in parallel', function() {
  224. it('should work as expected', function(originalDone) {
  225. var path = '/x';
  226. var message = 'Hello world';
  227. var done = util.callNTimes(2, function() {
  228. server.close();
  229. originalDone();
  230. });
  231. var server = http2.createServer(serverOptions, function(request, response) {
  232. expect(request.url).to.equal(path);
  233. response.end(message);
  234. });
  235. server.listen(1234, function() {
  236. http2.get('https://localhost:1234' + path, function(response) {
  237. response.on('data', function(data) {
  238. expect(data.toString()).to.equal(message);
  239. done();
  240. });
  241. });
  242. http2.get('https://localhost:1234' + path, function(response) {
  243. response.on('data', function(data) {
  244. expect(data.toString()).to.equal(message);
  245. done();
  246. });
  247. });
  248. });
  249. });
  250. });
  251. describe('100 simple request in a series', function() {
  252. it('should work as expected', function(done) {
  253. var path = '/x';
  254. var message = 'Hello world';
  255. var server = http2.createServer(serverOptions, function(request, response) {
  256. expect(request.url).to.equal(path);
  257. response.end(message);
  258. });
  259. var n = 100;
  260. server.listen(1242, function() {
  261. doRequest();
  262. function doRequest() {
  263. http2.get('https://localhost:1242' + path, function(response) {
  264. response.on('data', function(data) {
  265. expect(data.toString()).to.equal(message);
  266. if (n) {
  267. n -= 1;
  268. doRequest();
  269. } else {
  270. server.close();
  271. done();
  272. }
  273. });
  274. });
  275. }
  276. });
  277. });
  278. });
  279. describe('request with payload', function() {
  280. it('should work as expected', function(done) {
  281. var path = '/x';
  282. var message = 'Hello world';
  283. var server = http2.createServer(serverOptions, function(request, response) {
  284. expect(request.url).to.equal(path);
  285. request.once('data', function(data) {
  286. expect(data.toString()).to.equal(message);
  287. response.end();
  288. });
  289. });
  290. server.listen(1240, function() {
  291. var request = http2.request({
  292. host: 'localhost',
  293. port: 1240,
  294. path: path
  295. });
  296. request.write(message);
  297. request.end();
  298. request.on('response', function() {
  299. server.close();
  300. done();
  301. });
  302. });
  303. });
  304. });
  305. describe('request with custom status code and headers', function() {
  306. it('should work as expected', function(done) {
  307. var path = '/x';
  308. var message = 'Hello world';
  309. var headerName = 'name';
  310. var headerValue = 'value';
  311. var server = http2.createServer(serverOptions, function(request, response) {
  312. // Request URL and headers
  313. expect(request.url).to.equal(path);
  314. expect(request.headers[headerName]).to.equal(headerValue);
  315. // A header to be overwritten later
  316. response.setHeader(headerName, 'to be overwritten');
  317. expect(response.getHeader(headerName)).to.equal('to be overwritten');
  318. // A header to be deleted
  319. response.setHeader('nonexistent', 'x');
  320. response.removeHeader('nonexistent');
  321. expect(response.getHeader('nonexistent')).to.equal(undefined);
  322. // A set-cookie header which should always be an array
  323. response.setHeader('set-cookie', 'foo');
  324. // Don't send date
  325. response.sendDate = false;
  326. // Specifying more headers, the status code and a reason phrase with `writeHead`
  327. var moreHeaders = {};
  328. moreHeaders[headerName] = headerValue;
  329. response.writeHead(600, 'to be discarded', moreHeaders);
  330. expect(response.getHeader(headerName)).to.equal(headerValue);
  331. // Empty response body
  332. response.end(message);
  333. });
  334. server.listen(1239, function() {
  335. var headers = {};
  336. headers[headerName] = headerValue;
  337. var request = http2.request({
  338. host: 'localhost',
  339. port: 1239,
  340. path: path,
  341. headers: headers
  342. });
  343. request.end();
  344. request.on('response', function(response) {
  345. expect(response.headers[headerName]).to.equal(headerValue);
  346. expect(response.headers['nonexistent']).to.equal(undefined);
  347. expect(response.headers['set-cookie']).to.an.instanceof(Array)
  348. expect(response.headers['set-cookie']).to.deep.equal(['foo'])
  349. expect(response.headers['date']).to.equal(undefined);
  350. response.on('data', function(data) {
  351. expect(data.toString()).to.equal(message);
  352. server.close();
  353. done();
  354. });
  355. });
  356. });
  357. });
  358. });
  359. describe('request over plain TCP', function() {
  360. it('should work as expected', function(done) {
  361. var path = '/x';
  362. var message = 'Hello world';
  363. var server = http2.raw.createServer({
  364. log: util.serverLog
  365. }, function(request, response) {
  366. expect(request.url).to.equal(path);
  367. response.end(message);
  368. });
  369. server.listen(1237, function() {
  370. var request = http2.raw.request({
  371. plain: true,
  372. host: 'localhost',
  373. port: 1237,
  374. path: path
  375. }, function(response) {
  376. response.on('data', function(data) {
  377. expect(data.toString()).to.equal(message);
  378. server.close();
  379. done();
  380. });
  381. });
  382. request.end();
  383. });
  384. });
  385. });
  386. describe('get over plain TCP', function() {
  387. it('should work as expected', function(done) {
  388. var path = '/x';
  389. var message = 'Hello world';
  390. var server = http2.raw.createServer({
  391. log: util.serverLog
  392. }, function(request, response) {
  393. expect(request.url).to.equal(path);
  394. response.end(message);
  395. });
  396. server.listen(1237, function() {
  397. var request = http2.raw.get('http://localhost:1237/x', function(response) {
  398. response.on('data', function(data) {
  399. expect(data.toString()).to.equal(message);
  400. server.close();
  401. done();
  402. });
  403. });
  404. request.end();
  405. });
  406. });
  407. });
  408. describe('request to an HTTPS/1 server', function() {
  409. it('should fall back to HTTPS/1 successfully', function(done) {
  410. var path = '/x';
  411. var message = 'Hello world';
  412. var server = https.createServer(serverOptions, function(request, response) {
  413. expect(request.url).to.equal(path);
  414. response.end(message);
  415. });
  416. server.listen(5678, function() {
  417. http2.get('https://localhost:5678' + path, function(response) {
  418. response.on('data', function(data) {
  419. expect(data.toString()).to.equal(message);
  420. done();
  421. });
  422. });
  423. });
  424. });
  425. });
  426. describe('2 parallel request to an HTTPS/1 server', function() {
  427. it('should fall back to HTTPS/1 successfully', function(originalDone) {
  428. var path = '/x';
  429. var message = 'Hello world';
  430. var done = util.callNTimes(2, function() {
  431. server.close();
  432. originalDone();
  433. });
  434. var server = https.createServer(serverOptions, function(request, response) {
  435. expect(request.url).to.equal(path);
  436. response.end(message);
  437. });
  438. server.listen(6789, function() {
  439. http2.get('https://localhost:6789' + path, function(response) {
  440. response.on('data', function(data) {
  441. expect(data.toString()).to.equal(message);
  442. done();
  443. });
  444. });
  445. http2.get('https://localhost:6789' + path, function(response) {
  446. response.on('data', function(data) {
  447. expect(data.toString()).to.equal(message);
  448. done();
  449. });
  450. });
  451. });
  452. });
  453. });
  454. describe('HTTPS/1 request to a HTTP/2 server', function() {
  455. it('should fall back to HTTPS/1 successfully', function(done) {
  456. var path = '/x';
  457. var message = 'Hello world';
  458. var server = http2.createServer(serverOptions, function(request, response) {
  459. expect(request.url).to.equal(path);
  460. response.end(message);
  461. });
  462. server.listen(1236, function() {
  463. var options = url.parse('https://localhost:1236' + path);
  464. options.agent = new https.Agent(agentOptions);
  465. https.get(options, function(response) {
  466. response.on('data', function(data) {
  467. expect(data.toString()).to.equal(message);
  468. done();
  469. });
  470. });
  471. });
  472. });
  473. });
  474. describe('two parallel request', function() {
  475. it('should work as expected', function(done) {
  476. var path = '/x';
  477. var message = 'Hello world';
  478. var server = http2.createServer(serverOptions, function(request, response) {
  479. expect(request.url).to.equal(path);
  480. response.end(message);
  481. });
  482. server.listen(1237, function() {
  483. done = util.callNTimes(2, done);
  484. // 1. request
  485. http2.get('https://localhost:1237' + path, function(response) {
  486. response.on('data', function(data) {
  487. expect(data.toString()).to.equal(message);
  488. done();
  489. });
  490. });
  491. // 2. request
  492. http2.get('https://localhost:1237' + path, function(response) {
  493. response.on('data', function(data) {
  494. expect(data.toString()).to.equal(message);
  495. done();
  496. });
  497. });
  498. });
  499. });
  500. });
  501. describe('two subsequent request', function() {
  502. it('should use the same HTTP/2 connection', function(done) {
  503. var path = '/x';
  504. var message = 'Hello world';
  505. var server = http2.createServer(serverOptions, function(request, response) {
  506. expect(request.url).to.equal(path);
  507. response.end(message);
  508. });
  509. server.listen(1238, function() {
  510. // 1. request
  511. http2.get('https://localhost:1238' + path, function(response) {
  512. response.on('data', function(data) {
  513. expect(data.toString()).to.equal(message);
  514. // 2. request
  515. http2.get('https://localhost:1238' + path, function(response) {
  516. response.on('data', function(data) {
  517. expect(data.toString()).to.equal(message);
  518. done();
  519. });
  520. });
  521. });
  522. });
  523. });
  524. });
  525. });
  526. describe('https server node module specification conformance', function() {
  527. it('should provide API for remote HTTP 1.1 client address', function(done) {
  528. var remoteAddress = null;
  529. var remotePort = null;
  530. var server = http2.createServer(serverOptions, function(request, response) {
  531. // HTTPS 1.1 client with Node 0.10 server
  532. if (!request.remoteAddress) {
  533. if (request.socket.socket) {
  534. remoteAddress = request.socket.socket.remoteAddress;
  535. remotePort = request.socket.socket.remotePort;
  536. } else {
  537. remoteAddress = request.socket.remoteAddress;
  538. remotePort = request.socket.remotePort;
  539. }
  540. } else {
  541. // HTTPS 1.1/2.0 client with Node 0.12 server
  542. remoteAddress = request.remoteAddress;
  543. remotePort = request.remotePort;
  544. }
  545. response.write('Pong');
  546. response.end();
  547. });
  548. server.listen(1259, 'localhost', function() {
  549. var request = https.request({
  550. host: 'localhost',
  551. port: 1259,
  552. path: '/',
  553. ca: serverOptions.cert
  554. });
  555. request.write('Ping');
  556. request.end();
  557. request.on('response', function(response) {
  558. response.on('data', function(data) {
  559. var localAddress = response.socket.address();
  560. expect(remoteAddress).to.equal(localAddress.address);
  561. expect(remotePort).to.equal(localAddress.port);
  562. server.close();
  563. done();
  564. });
  565. });
  566. });
  567. });
  568. it('should provide API for remote HTTP 2.0 client address', function(done) {
  569. var remoteAddress = null;
  570. var remotePort = null;
  571. var localAddress = null;
  572. var server = http2.createServer(serverOptions, function(request, response) {
  573. remoteAddress = request.remoteAddress;
  574. remotePort = request.remotePort;
  575. response.write('Pong');
  576. response.end();
  577. });
  578. server.listen(1258, 'localhost', function() {
  579. var request = http2.request({
  580. host: 'localhost',
  581. port: 1258,
  582. path: '/'
  583. });
  584. request.write('Ping');
  585. globalAgent.on('false:localhost:1258', function(endpoint) {
  586. localAddress = endpoint.socket.address();
  587. });
  588. request.end();
  589. request.on('response', function(response) {
  590. response.on('data', function(data) {
  591. expect(remoteAddress).to.equal(localAddress.address);
  592. expect(remotePort).to.equal(localAddress.port);
  593. server.close();
  594. done();
  595. });
  596. });
  597. });
  598. });
  599. it('should expose net.Socket as .socket and .connection', function(done) {
  600. var server = http2.createServer(serverOptions, function(request, response) {
  601. expect(request.socket).to.equal(request.connection);
  602. expect(request.socket).to.be.instanceof(net.Socket);
  603. response.write('Pong');
  604. response.end();
  605. done();
  606. });
  607. server.listen(1248, 'localhost', function() {
  608. var request = https.request({
  609. host: 'localhost',
  610. port: 1248,
  611. path: '/',
  612. ca: serverOptions.cert
  613. });
  614. request.write('Ping');
  615. request.end();
  616. });
  617. });
  618. });
  619. describe('request and response with trailers', function() {
  620. it('should work as expected', function(done) {
  621. var path = '/x';
  622. var message = 'Hello world';
  623. var requestTrailers = { 'content-md5': 'x' };
  624. var responseTrailers = { 'content-md5': 'y' };
  625. var server = http2.createServer(serverOptions, function(request, response) {
  626. expect(request.url).to.equal(path);
  627. request.on('data', util.noop);
  628. request.once('end', function() {
  629. expect(request.trailers).to.deep.equal(requestTrailers);
  630. response.write(message);
  631. response.addTrailers(responseTrailers);
  632. response.end();
  633. });
  634. });
  635. server.listen(1241, function() {
  636. var request = http2.request('https://localhost:1241' + path);
  637. request.addTrailers(requestTrailers);
  638. request.end();
  639. request.on('response', function(response) {
  640. response.on('data', util.noop);
  641. response.once('end', function() {
  642. expect(response.trailers).to.deep.equal(responseTrailers);
  643. done();
  644. });
  645. });
  646. });
  647. });
  648. });
  649. describe('Handle socket error', function () {
  650. it('HTTPS on Connection Refused error', function (done) {
  651. var path = '/x';
  652. var request = http2.request('https://127.0.0.1:6666' + path);
  653. request.on('error', function (err) {
  654. expect(err.errno).to.equal('ECONNREFUSED');
  655. done();
  656. });
  657. request.on('response', function (response) {
  658. server._server._handle.destroy();
  659. response.on('data', util.noop);
  660. response.once('end', function () {
  661. done(new Error('Request should have failed'));
  662. });
  663. });
  664. request.end();
  665. });
  666. it('HTTP on Connection Refused error', function (done) {
  667. var path = '/x';
  668. var request = http2.raw.request('http://127.0.0.1:6666' + path);
  669. request.on('error', function (err) {
  670. expect(err.errno).to.equal('ECONNREFUSED');
  671. done();
  672. });
  673. request.on('response', function (response) {
  674. server._server._handle.destroy();
  675. response.on('data', util.noop);
  676. response.once('end', function () {
  677. done(new Error('Request should have failed'));
  678. });
  679. });
  680. request.end();
  681. });
  682. });
  683. describe('server push', function() {
  684. it('should work as expected', function(done) {
  685. var path = '/x';
  686. var message = 'Hello world';
  687. var pushedPath = '/y';
  688. var pushedMessage = 'Hello world 2';
  689. var server = http2.createServer(serverOptions, function(request, response) {
  690. expect(request.url).to.equal(path);
  691. var push1 = response.push('/y');
  692. push1.end(pushedMessage);
  693. var push2 = response.push({ path: '/y', protocol: 'https:' });
  694. push2.end(pushedMessage);
  695. response.end(message);
  696. });
  697. server.listen(1235, function() {
  698. var request = http2.get('https://localhost:1235' + path);
  699. done = util.callNTimes(5, done);
  700. request.on('response', function(response) {
  701. response.on('data', function(data) {
  702. expect(data.toString()).to.equal(message);
  703. done();
  704. });
  705. response.on('end', done);
  706. });
  707. request.on('push', function(promise) {
  708. expect(promise.url).to.be.equal(pushedPath);
  709. promise.on('response', function(pushStream) {
  710. pushStream.on('data', function(data) {
  711. expect(data.toString()).to.equal(pushedMessage);
  712. done();
  713. });
  714. pushStream.on('end', done);
  715. });
  716. });
  717. });
  718. });
  719. });
  720. });
  721. });