Skip to content

Commit 11a2ca2

Browse files
starkwangrefack
authored andcommitted
errors: migrate _http_outgoing
PR-URL: #14735 Refs: #11273 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
1 parent 28a47aa commit 11a2ca2

14 files changed

+201
-96
lines changed

doc/api/errors.md

+5
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,11 @@ Used when an attempt is made to open an IPC communication channel with a
998998
synchronous forked Node.js process. See the documentation for the
999999
[`child_process`](child_process.html) module for more information.
10001000

1001+
<a id="ERR_METHOD_NOT_IMPLEMENTED"></a>
1002+
### ERR_METHOD_NOT_IMPLEMENTED
1003+
1004+
Used when a method is required but not implemented.
1005+
10011006
<a id="ERR_MISSING_ARGS"></a>
10021007
### ERR_MISSING_ARGS
10031008

lib/_http_client.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ function ClientRequest(options, cb) {
150150

151151
if (methodIsString && method) {
152152
if (!common._checkIsHttpToken(method)) {
153-
throw new errors.TypeError('ERR_INVALID_HTTP_TOKEN', 'Method');
153+
throw new errors.TypeError('ERR_INVALID_HTTP_TOKEN', 'Method', method);
154154
}
155155
method = this.method = method.toUpperCase();
156156
} else {
@@ -211,7 +211,7 @@ function ClientRequest(options, cb) {
211211
options.headers);
212212
} else if (this.getHeader('expect')) {
213213
if (this._header) {
214-
throw new errors.Error('ERR_HTTP_HEADERS_SENT');
214+
throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'render');
215215
}
216216

217217
this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n',
@@ -302,7 +302,7 @@ ClientRequest.prototype._finish = function _finish() {
302302

303303
ClientRequest.prototype._implicitHeader = function _implicitHeader() {
304304
if (this._header) {
305-
throw new errors.Error('ERR_HTTP_HEADERS_SENT');
305+
throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'render');
306306
}
307307
this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n',
308308
this[outHeadersKey]);

lib/_http_outgoing.js

+21-19
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ Object.defineProperty(OutgoingMessage.prototype, '_headerNames', {
163163

164164
OutgoingMessage.prototype._renderHeaders = function _renderHeaders() {
165165
if (this._header) {
166-
throw new Error('Can\'t render headers after they are sent to the client');
166+
throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'render');
167167
}
168168

169169
var headersMap = this[outHeadersKey];
@@ -433,14 +433,14 @@ function _storeHeader(firstLine, headers) {
433433
function storeHeader(self, state, key, value, validate) {
434434
if (validate) {
435435
if (typeof key !== 'string' || !key || !checkIsHttpToken(key)) {
436-
throw new TypeError(
437-
'Header name must be a valid HTTP Token ["' + key + '"]');
436+
throw new errors.TypeError(
437+
'ERR_INVALID_HTTP_TOKEN', 'Header name', key);
438438
}
439439
if (value === undefined) {
440-
throw new Error('Header "%s" value must not be undefined', key);
440+
throw new errors.TypeError('ERR_MISSING_ARGS', `header "${key}"`);
441441
} else if (checkInvalidHeaderChar(value)) {
442442
debug('Header "%s" contains invalid characters', key);
443-
throw new TypeError('The header content contains invalid characters');
443+
throw new errors.TypeError('ERR_INVALID_CHAR', 'header content', key);
444444
}
445445
}
446446
state.header += key + ': ' + escapeHeaderValue(value) + CRLF;
@@ -491,14 +491,14 @@ function matchHeader(self, state, field, value) {
491491

492492
function validateHeader(msg, name, value) {
493493
if (typeof name !== 'string' || !name || !checkIsHttpToken(name))
494-
throw new TypeError(`Header name must be a valid HTTP Token ["${name}"]`);
494+
throw new errors.TypeError('ERR_INVALID_HTTP_TOKEN', 'Header name', name);
495495
if (value === undefined)
496-
throw new Error('"value" required in setHeader("' + name + '", value)');
496+
throw new errors.TypeError('ERR_MISSING_ARGS', 'value');
497497
if (msg._header)
498-
throw new Error('Can\'t set headers after they are sent.');
498+
throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'set');
499499
if (checkInvalidHeaderChar(value)) {
500500
debug('Header "%s" contains invalid characters', name);
501-
throw new TypeError('The header content contains invalid characters');
501+
throw new errors.TypeError('ERR_INVALID_CHAR', 'header content', name);
502502
}
503503
}
504504
OutgoingMessage.prototype.setHeader = function setHeader(name, value) {
@@ -529,7 +529,7 @@ OutgoingMessage.prototype.setHeader = function setHeader(name, value) {
529529

530530
OutgoingMessage.prototype.getHeader = function getHeader(name) {
531531
if (typeof name !== 'string') {
532-
throw new TypeError('"name" argument must be a string');
532+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'name', 'string');
533533
}
534534

535535
if (!this[outHeadersKey]) return;
@@ -565,7 +565,7 @@ OutgoingMessage.prototype.getHeaders = function getHeaders() {
565565

566566
OutgoingMessage.prototype.hasHeader = function hasHeader(name) {
567567
if (typeof name !== 'string') {
568-
throw new TypeError('"name" argument must be a string');
568+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'name', 'string');
569569
}
570570

571571
return !!(this[outHeadersKey] && this[outHeadersKey][name.toLowerCase()]);
@@ -574,11 +574,11 @@ OutgoingMessage.prototype.hasHeader = function hasHeader(name) {
574574

575575
OutgoingMessage.prototype.removeHeader = function removeHeader(name) {
576576
if (typeof name !== 'string') {
577-
throw new TypeError('"name" argument must be a string');
577+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'name', 'string');
578578
}
579579

580580
if (this._header) {
581-
throw new Error('Can\'t remove headers after they are sent');
581+
throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'remove');
582582
}
583583

584584
var key = name.toLowerCase();
@@ -609,7 +609,7 @@ OutgoingMessage.prototype.removeHeader = function removeHeader(name) {
609609

610610

611611
OutgoingMessage.prototype._implicitHeader = function _implicitHeader() {
612-
throw new Error('_implicitHeader() method is not implemented');
612+
throw new errors.Error('ERR_METHOD_NOT_IMPLEMENTED', '_implicitHeader()');
613613
};
614614

615615
Object.defineProperty(OutgoingMessage.prototype, 'headersSent', {
@@ -646,7 +646,8 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
646646
}
647647

648648
if (!fromEnd && typeof chunk !== 'string' && !(chunk instanceof Buffer)) {
649-
throw new TypeError('First argument must be a string or Buffer');
649+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'first argument',
650+
['string', 'buffer']);
650651
}
651652

652653

@@ -712,12 +713,12 @@ OutgoingMessage.prototype.addTrailers = function addTrailers(headers) {
712713
value = headers[key];
713714
}
714715
if (typeof field !== 'string' || !field || !checkIsHttpToken(field)) {
715-
throw new TypeError(
716-
'Trailer name must be a valid HTTP Token ["' + field + '"]');
716+
throw new errors.TypeError('ERR_INVALID_HTTP_TOKEN', 'Trailer name',
717+
field);
717718
}
718719
if (checkInvalidHeaderChar(value)) {
719720
debug('Trailer "%s" contains invalid characters', field);
720-
throw new TypeError('The trailer content contains invalid characters');
721+
throw new errors.TypeError('ERR_INVALID_CHAR', 'trailer content', field);
721722
}
722723
this._trailer += field + ': ' + escapeHeaderValue(value) + CRLF;
723724
}
@@ -743,7 +744,8 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
743744
var uncork;
744745
if (chunk) {
745746
if (typeof chunk !== 'string' && !(chunk instanceof Buffer)) {
746-
throw new TypeError('First argument must be a string or Buffer');
747+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'first argument',
748+
['string', 'buffer']);
747749
}
748750
if (!this._header) {
749751
if (typeof chunk === 'string')

lib/_http_server.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ function writeHead(statusCode, reason, obj) {
214214
}
215215
}
216216
if (k === undefined && this._header) {
217-
throw new errors.Error('ERR_HTTP_HEADERS_SENT');
217+
throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'render');
218218
}
219219
// only progressive api is used
220220
headers = this[outHeadersKey];

lib/internal/errors.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ E('ERR_ENCODING_NOT_SUPPORTED',
114114
E('ERR_ENCODING_INVALID_ENCODED_DATA',
115115
(enc) => `The encoded data was not valid for encoding ${enc}`);
116116
E('ERR_HTTP_HEADERS_SENT',
117-
'Cannot render headers after they are sent to the client');
117+
'Cannot %s headers after they are sent to the client');
118118
E('ERR_HTTP_INVALID_STATUS_CODE', 'Invalid status code: %s');
119119
E('ERR_HTTP_TRAILER_INVALID',
120120
'Trailers are invalid with this transfer encoding');
@@ -190,7 +190,7 @@ E('ERR_INVALID_ARRAY_LENGTH',
190190
});
191191
E('ERR_INVALID_BUFFER_SIZE', 'Buffer size must be a multiple of %s');
192192
E('ERR_INVALID_CALLBACK', 'Callback must be a function');
193-
E('ERR_INVALID_CHAR', 'Invalid character in %s');
193+
E('ERR_INVALID_CHAR', invalidChar);
194194
E('ERR_INVALID_CURSOR_POS',
195195
'Cannot set cursor row without setting its column');
196196
E('ERR_INVALID_DOMAIN_NAME', 'Unable to determine the domain name');
@@ -199,7 +199,7 @@ E('ERR_INVALID_FILE_URL_HOST',
199199
'File URL host must be "localhost" or empty on %s');
200200
E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s');
201201
E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent');
202-
E('ERR_INVALID_HTTP_TOKEN', (name) => `${name} must be a valid HTTP token`);
202+
E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]');
203203
E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s');
204204
E('ERR_INVALID_OPT_VALUE',
205205
(name, value) => {
@@ -222,6 +222,7 @@ E('ERR_IPC_CHANNEL_CLOSED', 'Channel closed');
222222
E('ERR_IPC_DISCONNECTED', 'IPC channel is already disconnected');
223223
E('ERR_IPC_ONE_PIPE', 'Child process can have only one IPC pipe');
224224
E('ERR_IPC_SYNC_FORK', 'IPC cannot be used with synchronous forks');
225+
E('ERR_METHOD_NOT_IMPLEMENTED', 'The %s method is not implemented');
225226
E('ERR_MISSING_ARGS', missingArgs);
226227
E('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times');
227228
E('ERR_NAPI_CONS_FUNCTION', 'Constructor must be a function');
@@ -342,3 +343,11 @@ function bufferOutOfBounds(name, isWriting) {
342343
return `"${name}" is outside of buffer bounds`;
343344
}
344345
}
346+
347+
function invalidChar(name, field) {
348+
let msg = `Invalid character in ${name}`;
349+
if (field) {
350+
msg += ` ["${field}"]`;
351+
}
352+
return msg;
353+
}

test/parallel/test-http-mutable-headers.js

+49-24
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,38 @@ const s = http.createServer(common.mustCall((req, res) => {
5050
assert.deepStrictEqual(res.hasHeader('Connection'), false);
5151
assert.deepStrictEqual(res.getHeader('Connection'), undefined);
5252

53-
assert.throws(() => {
54-
res.setHeader();
55-
}, /^TypeError: Header name must be a valid HTTP Token \["undefined"\]$/);
56-
assert.throws(() => {
57-
res.setHeader('someHeader');
58-
}, /^Error: "value" required in setHeader\("someHeader", value\)$/);
59-
assert.throws(() => {
60-
res.getHeader();
61-
}, /^TypeError: "name" argument must be a string$/);
62-
assert.throws(() => {
63-
res.removeHeader();
64-
}, /^TypeError: "name" argument must be a string$/);
53+
common.expectsError(
54+
() => res.setHeader(),
55+
{
56+
code: 'ERR_INVALID_HTTP_TOKEN',
57+
type: TypeError,
58+
message: 'Header name must be a valid HTTP token ["undefined"]'
59+
}
60+
);
61+
common.expectsError(
62+
() => res.setHeader('someHeader'),
63+
{
64+
code: 'ERR_MISSING_ARGS',
65+
type: TypeError,
66+
message: 'The "value" argument must be specified'
67+
}
68+
);
69+
common.expectsError(
70+
() => res.getHeader(),
71+
{
72+
code: 'ERR_INVALID_ARG_TYPE',
73+
type: TypeError,
74+
message: 'The "name" argument must be of type string'
75+
}
76+
);
77+
common.expectsError(
78+
() => res.removeHeader(),
79+
{
80+
code: 'ERR_INVALID_ARG_TYPE',
81+
type: TypeError,
82+
message: 'The "name" argument must be of type string'
83+
}
84+
);
6585

6686
const arrayValues = [1, 2, 3];
6787
res.setHeader('x-test-header', 'testing');
@@ -89,18 +109,23 @@ const s = http.createServer(common.mustCall((req, res) => {
89109
assert.strictEqual(res.hasHeader('x-test-header2'), true);
90110
assert.strictEqual(res.hasHeader('X-TEST-HEADER2'), true);
91111
assert.strictEqual(res.hasHeader('X-Test-Header2'), true);
92-
assert.throws(() => {
93-
res.hasHeader();
94-
}, /^TypeError: "name" argument must be a string$/);
95-
assert.throws(() => {
96-
res.hasHeader(null);
97-
}, /^TypeError: "name" argument must be a string$/);
98-
assert.throws(() => {
99-
res.hasHeader(true);
100-
}, /^TypeError: "name" argument must be a string$/);
101-
assert.throws(() => {
102-
res.hasHeader({ toString: () => 'X-TEST-HEADER2' });
103-
}, /^TypeError: "name" argument must be a string$/);
112+
[
113+
undefined,
114+
null,
115+
true,
116+
{},
117+
{ toString: () => 'X-TEST-HEADER2' },
118+
() => { }
119+
].forEach((val) => {
120+
common.expectsError(
121+
() => res.hasHeader(val),
122+
{
123+
code: 'ERR_INVALID_ARG_TYPE',
124+
type: TypeError,
125+
message: 'The "name" argument must be of type string'
126+
}
127+
);
128+
});
104129

105130
res.removeHeader('x-test-header2');
106131

0 commit comments

Comments
 (0)