1// Flags: --expose-internals 2 3'use strict'; 4 5const common = require('../common'); 6if (!common.hasCrypto) 7 common.skip('missing crypto'); 8const assert = require('assert'); 9const h2 = require('http2'); 10const net = require('net'); 11 12const { kTimeout } = require('internal/timers'); 13 14// Tests behavior of the proxied socket in Http2ServerRequest 15// & Http2ServerResponse - this proxy socket should mimic the 16// behavior of http1 but against the http2 api & model 17 18const errMsg = { 19 code: 'ERR_HTTP2_NO_SOCKET_MANIPULATION', 20 name: 'Error', 21 message: 'HTTP/2 sockets should not be directly manipulated ' + 22 '(e.g. read and written)' 23}; 24 25const server = h2.createServer(); 26 27server.on('request', common.mustCall(function(request, response) { 28 assert.ok(request.socket instanceof net.Socket); 29 assert.ok(response.socket instanceof net.Socket); 30 assert.strictEqual(request.socket, response.socket); 31 32 assert.ok(request.socket.readable); 33 request.resume(); 34 assert.ok(request.socket.writable); 35 assert.strictEqual(request.socket.destroyed, false); 36 37 request.socket.setTimeout(987); 38 assert.strictEqual(request.stream.session[kTimeout]._idleTimeout, 987); 39 request.socket.setTimeout(0); 40 41 assert.throws(() => request.socket.read(), errMsg); 42 assert.throws(() => request.socket.write(), errMsg); 43 assert.throws(() => request.socket.pause(), errMsg); 44 assert.throws(() => request.socket.resume(), errMsg); 45 46 // Should have correct this context for socket methods & getters 47 assert.ok(request.socket.address() != null); 48 assert.ok(request.socket.remotePort); 49 50 request.on('end', common.mustCall(() => { 51 assert.strictEqual(request.socket.readable, false); 52 response.socket.destroy(); 53 })); 54 response.on('finish', common.mustCall(() => { 55 assert.ok(request.socket); 56 assert.strictEqual(response.socket, undefined); 57 assert.ok(request.socket.destroyed); 58 assert.strictEqual(request.socket.readable, false); 59 process.nextTick(() => { 60 assert.strictEqual(request.socket.writable, false); 61 server.close(); 62 }); 63 })); 64 65 // Properties that do not exist on the proxy are retrieved from the socket 66 assert.ok(request.socket._server); 67 assert.strictEqual(request.socket.connecting, false); 68 69 // Socket events are bound and emitted on Http2Stream 70 request.socket.on('close', common.mustCall()); 71 request.socket.once('close', common.mustCall()); 72 request.socket.on('testEvent', common.mustCall()); 73 request.socket.emit('testEvent'); 74})); 75 76server.listen(0, common.mustCall(function() { 77 const port = server.address().port; 78 const url = `http://localhost:${port}`; 79 const client = h2.connect(url, common.mustCall(() => { 80 const headers = { 81 ':path': '/', 82 ':method': 'GET', 83 ':scheme': 'http', 84 ':authority': `localhost:${port}` 85 }; 86 const request = client.request(headers); 87 request.on('end', common.mustCall(() => { 88 client.close(); 89 })); 90 request.end(); 91 request.resume(); 92 })); 93})); 94