1'use strict'; 2 3const common = require('../common'); 4if (!common.hasCrypto) 5 common.skip('missing crypto'); 6const fixtures = require('../common/fixtures'); 7const assert = require('assert'); 8const http2 = require('http2'); 9const fs = require('fs'); 10const { inspect } = require('util'); 11 12const optionsWithTypeError = { 13 offset: 'number', 14 length: 'number', 15 statCheck: 'function' 16}; 17 18const types = { 19 boolean: true, 20 function: () => {}, 21 number: 1, 22 object: {}, 23 array: [], 24 null: null, 25 symbol: Symbol('test') 26}; 27 28const fname = fixtures.path('elipses.txt'); 29const fd = fs.openSync(fname, 'r'); 30 31const server = http2.createServer(); 32 33server.on('stream', common.mustCall((stream) => { 34 // Should throw if fd isn't a number 35 Object.keys(types).forEach((type) => { 36 if (type === 'number') { 37 return; 38 } 39 40 assert.throws( 41 () => stream.respondWithFD(types[type], { 42 'content-type': 'text/plain' 43 }), 44 { 45 name: 'TypeError', 46 code: 'ERR_INVALID_ARG_TYPE', 47 message: 'The "fd" argument must be of type number or an instance of' + 48 ` FileHandle.${common.invalidArgTypeHelper(types[type])}` 49 } 50 ); 51 }); 52 53 // Check for all possible TypeError triggers on options 54 Object.keys(optionsWithTypeError).forEach((option) => { 55 Object.keys(types).forEach((type) => { 56 if (type === optionsWithTypeError[option]) { 57 return; 58 } 59 60 assert.throws( 61 () => stream.respondWithFD(fd, { 62 'content-type': 'text/plain' 63 }, { 64 [option]: types[type] 65 }), 66 { 67 name: 'TypeError', 68 code: 'ERR_INVALID_OPT_VALUE', 69 message: `The value "${inspect(types[type])}" is invalid ` + 70 `for option "${option}"` 71 } 72 ); 73 }); 74 }); 75 76 // Should throw if :status 204, 205 or 304 77 [204, 205, 304].forEach((status) => assert.throws( 78 () => stream.respondWithFD(fd, { 79 'content-type': 'text/plain', 80 ':status': status, 81 }), 82 { 83 code: 'ERR_HTTP2_PAYLOAD_FORBIDDEN', 84 name: 'Error', 85 message: `Responses with ${status} status must not have a payload` 86 } 87 )); 88 89 // Should throw if headers already sent 90 stream.respond(); 91 assert.throws( 92 () => stream.respondWithFD(fd, { 93 'content-type': 'text/plain' 94 }), 95 { 96 code: 'ERR_HTTP2_HEADERS_SENT', 97 name: 'Error', 98 message: 'Response has already been initiated.' 99 } 100 ); 101 102 // Should throw if stream already destroyed 103 stream.destroy(); 104 assert.throws( 105 () => stream.respondWithFD(fd, { 106 'content-type': 'text/plain' 107 }), 108 { 109 code: 'ERR_HTTP2_INVALID_STREAM', 110 name: 'Error', 111 message: 'The stream has been destroyed' 112 } 113 ); 114})); 115 116server.listen(0, common.mustCall(() => { 117 const client = http2.connect(`http://localhost:${server.address().port}`); 118 const req = client.request(); 119 120 req.on('close', common.mustCall(() => { 121 client.close(); 122 server.close(); 123 })); 124 req.end(); 125})); 126