mirror of https://github.com/lukechilds/node.git
Browse Source
Fix references within http2 core to HTTP_STATUS_CONTENT_RESET to point to the correct HTTP_STATUS_RESET_CONTENT. Add tests for status 204, 205 & 304 in respond, respondWithFD & respondWithFile. Add general error tests for respondWithFD & respondWithFile. PR-URL: https://github.com/nodejs/node/pull/15153 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Claudio Rodriguez <cjrodr@yahoo.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>canary-base
committed by
Ruben Bridgewater
4 changed files with 270 additions and 4 deletions
@ -0,0 +1,103 @@ |
|||||
|
// Flags: --expose-http2
|
||||
|
'use strict'; |
||||
|
|
||||
|
const common = require('../common'); |
||||
|
if (!common.hasCrypto) |
||||
|
common.skip('missing crypto'); |
||||
|
const http2 = require('http2'); |
||||
|
const path = require('path'); |
||||
|
|
||||
|
const optionsWithTypeError = { |
||||
|
offset: 'number', |
||||
|
length: 'number', |
||||
|
statCheck: 'function', |
||||
|
getTrailers: 'function' |
||||
|
}; |
||||
|
|
||||
|
const types = { |
||||
|
boolean: true, |
||||
|
function: () => {}, |
||||
|
number: 1, |
||||
|
object: {}, |
||||
|
array: [], |
||||
|
null: null, |
||||
|
symbol: Symbol('test') |
||||
|
}; |
||||
|
|
||||
|
const fname = path.resolve(common.fixturesDir, 'elipses.txt'); |
||||
|
|
||||
|
const server = http2.createServer(); |
||||
|
|
||||
|
server.on('stream', common.mustCall((stream) => { |
||||
|
// Check for all possible TypeError triggers on options
|
||||
|
Object.keys(optionsWithTypeError).forEach((option) => { |
||||
|
Object.keys(types).forEach((type) => { |
||||
|
if (type === optionsWithTypeError[option]) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
common.expectsError( |
||||
|
() => stream.respondWithFile(fname, { |
||||
|
[http2.constants.HTTP2_HEADER_CONTENT_TYPE]: 'text/plain' |
||||
|
}, { |
||||
|
[option]: types[type] |
||||
|
}), |
||||
|
{ |
||||
|
type: TypeError, |
||||
|
code: 'ERR_INVALID_OPT_VALUE', |
||||
|
message: `The value "${String(types[type])}" is invalid ` + |
||||
|
`for option "${option}"` |
||||
|
} |
||||
|
); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
// Should throw if :status 204, 205 or 304
|
||||
|
[204, 205, 304].forEach((status) => common.expectsError( |
||||
|
() => stream.respondWithFile(fname, { |
||||
|
[http2.constants.HTTP2_HEADER_CONTENT_TYPE]: 'text/plain', |
||||
|
':status': status, |
||||
|
}), |
||||
|
{ |
||||
|
code: 'ERR_HTTP2_PAYLOAD_FORBIDDEN', |
||||
|
message: `Responses with ${status} status must not have a payload` |
||||
|
} |
||||
|
)); |
||||
|
|
||||
|
// Should throw if headers already sent
|
||||
|
stream.respond({ |
||||
|
':status': 200, |
||||
|
}); |
||||
|
common.expectsError( |
||||
|
() => stream.respondWithFile(fname, { |
||||
|
[http2.constants.HTTP2_HEADER_CONTENT_TYPE]: 'text/plain' |
||||
|
}), |
||||
|
{ |
||||
|
code: 'ERR_HTTP2_HEADERS_SENT', |
||||
|
message: 'Response has already been initiated.' |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
// Should throw if stream already destroyed
|
||||
|
stream.destroy(); |
||||
|
common.expectsError( |
||||
|
() => stream.respondWithFile(fname, { |
||||
|
[http2.constants.HTTP2_HEADER_CONTENT_TYPE]: 'text/plain' |
||||
|
}), |
||||
|
{ |
||||
|
code: 'ERR_HTTP2_INVALID_STREAM', |
||||
|
message: 'The stream has been destroyed' |
||||
|
} |
||||
|
); |
||||
|
})); |
||||
|
|
||||
|
server.listen(0, common.mustCall(() => { |
||||
|
const client = http2.connect(`http://localhost:${server.address().port}`); |
||||
|
const req = client.request(); |
||||
|
|
||||
|
req.on('streamClosed', common.mustCall(() => { |
||||
|
client.destroy(); |
||||
|
server.close(); |
||||
|
})); |
||||
|
req.end(); |
||||
|
})); |
@ -0,0 +1,123 @@ |
|||||
|
// Flags: --expose-http2
|
||||
|
'use strict'; |
||||
|
|
||||
|
const common = require('../common'); |
||||
|
if (!common.hasCrypto) |
||||
|
common.skip('missing crypto'); |
||||
|
const http2 = require('http2'); |
||||
|
const path = require('path'); |
||||
|
const fs = require('fs'); |
||||
|
|
||||
|
const optionsWithTypeError = { |
||||
|
offset: 'number', |
||||
|
length: 'number', |
||||
|
statCheck: 'function', |
||||
|
getTrailers: 'function' |
||||
|
}; |
||||
|
|
||||
|
const types = { |
||||
|
boolean: true, |
||||
|
function: () => {}, |
||||
|
number: 1, |
||||
|
object: {}, |
||||
|
array: [], |
||||
|
null: null, |
||||
|
symbol: Symbol('test') |
||||
|
}; |
||||
|
|
||||
|
const fname = path.resolve(common.fixturesDir, 'elipses.txt'); |
||||
|
const fd = fs.openSync(fname, 'r'); |
||||
|
|
||||
|
const server = http2.createServer(); |
||||
|
|
||||
|
server.on('stream', common.mustCall((stream) => { |
||||
|
// should throw if fd isn't a number
|
||||
|
Object.keys(types).forEach((type) => { |
||||
|
if (type === 'number') { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
common.expectsError( |
||||
|
() => stream.respondWithFD(types[type], { |
||||
|
[http2.constants.HTTP2_HEADER_CONTENT_TYPE]: 'text/plain' |
||||
|
}), |
||||
|
{ |
||||
|
type: TypeError, |
||||
|
code: 'ERR_INVALID_ARG_TYPE', |
||||
|
message: 'The "fd" argument must be of type number' |
||||
|
} |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
// Check for all possible TypeError triggers on options
|
||||
|
Object.keys(optionsWithTypeError).forEach((option) => { |
||||
|
Object.keys(types).forEach((type) => { |
||||
|
if (type === optionsWithTypeError[option]) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
common.expectsError( |
||||
|
() => stream.respondWithFD(fd, { |
||||
|
[http2.constants.HTTP2_HEADER_CONTENT_TYPE]: 'text/plain' |
||||
|
}, { |
||||
|
[option]: types[type] |
||||
|
}), |
||||
|
{ |
||||
|
type: TypeError, |
||||
|
code: 'ERR_INVALID_OPT_VALUE', |
||||
|
message: `The value "${String(types[type])}" is invalid ` + |
||||
|
`for option "${option}"` |
||||
|
} |
||||
|
); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
// Should throw if :status 204, 205 or 304
|
||||
|
[204, 205, 304].forEach((status) => common.expectsError( |
||||
|
() => stream.respondWithFD(fd, { |
||||
|
[http2.constants.HTTP2_HEADER_CONTENT_TYPE]: 'text/plain', |
||||
|
':status': status, |
||||
|
}), |
||||
|
{ |
||||
|
code: 'ERR_HTTP2_PAYLOAD_FORBIDDEN', |
||||
|
message: `Responses with ${status} status must not have a payload` |
||||
|
} |
||||
|
)); |
||||
|
|
||||
|
// Should throw if headers already sent
|
||||
|
stream.respond({ |
||||
|
':status': 200, |
||||
|
}); |
||||
|
common.expectsError( |
||||
|
() => stream.respondWithFD(fd, { |
||||
|
[http2.constants.HTTP2_HEADER_CONTENT_TYPE]: 'text/plain' |
||||
|
}), |
||||
|
{ |
||||
|
code: 'ERR_HTTP2_HEADERS_SENT', |
||||
|
message: 'Response has already been initiated.' |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
// Should throw if stream already destroyed
|
||||
|
stream.destroy(); |
||||
|
common.expectsError( |
||||
|
() => stream.respondWithFD(fd, { |
||||
|
[http2.constants.HTTP2_HEADER_CONTENT_TYPE]: 'text/plain' |
||||
|
}), |
||||
|
{ |
||||
|
code: 'ERR_HTTP2_INVALID_STREAM', |
||||
|
message: 'The stream has been destroyed' |
||||
|
} |
||||
|
); |
||||
|
})); |
||||
|
|
||||
|
server.listen(0, common.mustCall(() => { |
||||
|
const client = http2.connect(`http://localhost:${server.address().port}`); |
||||
|
const req = client.request(); |
||||
|
|
||||
|
req.on('streamClosed', common.mustCall(() => { |
||||
|
client.destroy(); |
||||
|
server.close(); |
||||
|
})); |
||||
|
req.end(); |
||||
|
})); |
@ -0,0 +1,40 @@ |
|||||
|
// Flags: --expose-http2
|
||||
|
'use strict'; |
||||
|
|
||||
|
const common = require('../common'); |
||||
|
if (!common.hasCrypto) |
||||
|
common.skip('missing crypto'); |
||||
|
const http2 = require('http2'); |
||||
|
const assert = require('assert'); |
||||
|
|
||||
|
const server = http2.createServer(); |
||||
|
|
||||
|
// Check that stream ends immediately after respond on :status 204, 205 & 304
|
||||
|
|
||||
|
const status = [204, 205, 304]; |
||||
|
|
||||
|
server.on('stream', common.mustCall((stream) => { |
||||
|
stream.on('streamClosed', common.mustCall(() => { |
||||
|
assert.strictEqual(stream.destroyed, true); |
||||
|
})); |
||||
|
stream.respond({ ':status': status.shift() }); |
||||
|
}, 3)); |
||||
|
|
||||
|
server.listen(0, common.mustCall(makeRequest)); |
||||
|
|
||||
|
function makeRequest() { |
||||
|
const client = http2.connect(`http://localhost:${server.address().port}`); |
||||
|
const req = client.request(); |
||||
|
req.resume(); |
||||
|
|
||||
|
req.on('end', common.mustCall(() => { |
||||
|
client.destroy(); |
||||
|
|
||||
|
if (!status.length) { |
||||
|
server.close(); |
||||
|
} else { |
||||
|
makeRequest(); |
||||
|
} |
||||
|
})); |
||||
|
req.end(); |
||||
|
} |
Loading…
Reference in new issue