Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
Merge nodejs/master
Browse files Browse the repository at this point in the history
Merge 4d893e0 as of 2017-08-27.
This is an automatically created merge. For any problems please
contact @kunalspathak.
  • Loading branch information
chakrabot committed Sep 6, 2017
2 parents 85767d6 + 4d893e0 commit 9a8953d
Show file tree
Hide file tree
Showing 26 changed files with 506 additions and 382 deletions.
3 changes: 2 additions & 1 deletion BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ Prerequisites:
including the Community edition (remember to select
"Common Tools for Visual C++ 2015" feature during installation).
* [Visual Studio 2017](https://www.visualstudio.com/downloads/), any edition (including the Build Tools SKU).
**Required Components:** "MSbuild", "VC++ 2017 v141 toolset" and one of the Windows SDKs (10 or 8.1).
**Required Components:** "MSbuild", "VC++ 2017 v141 toolset" and at least one of the Windows SDKs.
*Note*: For "Windows 10 SDK (10.0.15063.0)" only the "Desktop C++ x86 and x64" flavor is required.
* Basic Unix tools required for some tests,
[Git for Windows](http://git-scm.com/download/win) includes Git Bash
and tools which can be included in the global `PATH`.
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ test-all-valgrind: test-build
$(PYTHON) tools/test.py --mode=debug,release --valgrind

CI_NATIVE_SUITES := addons addons-napi
CI_JS_SUITES := async-hooks doctool inspector known_issues message parallel pseudo-tty sequential
CI_JS_SUITES := abort async-hooks doctool inspector known_issues message parallel pseudo-tty sequential

# Build and test addons without building anything else
test-ci-native: LOGLEVEL := info
Expand Down
5 changes: 5 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,11 @@ are most likely an indication of a bug within Node.js itself.
Used when the V8 BreakIterator API is used but the full ICU data set is not
installed.

<a id="ERR_VALUE_OUT_OF_RANGE"></a>
### ERR_VALUE_OUT_OF_RANGE

Used when a given value is out of the accepted range.

[`ERR_INVALID_ARG_TYPE`]: #ERR_INVALID_ARG_TYPE
[`subprocess.kill()`]: child_process.html#child_process_subprocess_kill_signal
[`subprocess.send()`]: child_process.html#child_process_subprocess_send_message_sendhandle_options_callback
Expand Down
39 changes: 4 additions & 35 deletions doc/api/http2.md
Original file line number Diff line number Diff line change
Expand Up @@ -1118,8 +1118,6 @@ added: v8.4.0
* `headers` {[Headers Object][]}
* `options` {Object}
* `statCheck` {Function}
* `onError` {Function} Callback function invoked in the case of an
Error before send
* `getTrailers` {Function} Callback function invoked to collect trailer
headers.
* `offset` {number} The offset position at which to begin reading
Expand Down Expand Up @@ -1148,16 +1146,6 @@ server.on('stream', (stream) => {
function statCheck(stat, headers) {
headers['last-modified'] = stat.mtime.toUTCString();
}

function onError(err) {
if (err.code === 'ENOENT') {
stream.respond({ ':status': 404 });
} else {
stream.respond({ ':status': 500 });
}
stream.end();
}

stream.respondWithFile('/some/file',
{ 'content-type': 'text/plain' },
{ statCheck });
Expand Down Expand Up @@ -1190,10 +1178,6 @@ The `offset` and `length` options may be used to limit the response to a
specific range subset. This can be used, for instance, to support HTTP Range
requests.

The `options.onError` function may also be used to handle all the errors
that could happen before the delivery of the file is initiated. The
default behavior is to destroy the stream.

When set, the `options.getTrailers()` function is called immediately after
queuing the last chunk of payload data to be sent. The callback is passed a
single object (with a `null` prototype) that the listener may used to specify
Expand Down Expand Up @@ -1224,19 +1208,6 @@ added: v8.4.0

* Extends: {net.Server}

In `Http2Server`, there is no `'clientError'` event as there is in
HTTP1. However, there are `'socketError'`, `'sessionError'`, and
`'streamError'`, for error happened on the socket, session or stream
respectively.

#### Event: 'socketError'
<!-- YAML
added: v8.4.0
-->

The `'socketError'` event is emitted when a `'socketError'` event is emitted by
an `Http2Session` associated with the server.

#### Event: 'sessionError'
<!-- YAML
added: v8.4.0
Expand All @@ -1246,15 +1217,13 @@ The `'sessionError'` event is emitted when an `'error'` event is emitted by
an `Http2Session` object. If no listener is registered for this event, an
`'error'` event is emitted.

#### Event: 'streamError'
#### Event: 'socketError'
<!-- YAML
added: REPLACEME
added: v8.4.0
-->

* `socket` {http2.ServerHttp2Stream}

If an `ServerHttp2Stream` emits an `'error'` event, it will be forwarded here.
The stream will already be destroyed when this event is triggered.
The `'socketError'` event is emitted when a `'socketError'` event is emitted by
an `Http2Session` associated with the server.

#### Event: 'stream'
<!-- YAML
Expand Down
34 changes: 24 additions & 10 deletions lib/_tls_common.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
'use strict';

const tls = require('tls');
const errors = require('internal/errors');

const SSL_OP_CIPHER_SERVER_PREFERENCE =
process.binding('constants').crypto.SSL_OP_CIPHER_SERVER_PREFERENCE;
Expand Down Expand Up @@ -52,6 +53,14 @@ function SecureContext(secureProtocol, secureOptions, context) {
if (secureOptions) this.context.setOptions(secureOptions);
}

function validateKeyCert(value, type) {
if (typeof value !== 'string' && !ArrayBuffer.isView(value))
throw new errors.TypeError(
'ERR_INVALID_ARG_TYPE', type,
['string', 'Buffer', 'TypedArray', 'DataView']
);
}

exports.SecureContext = SecureContext;


Expand All @@ -71,10 +80,12 @@ exports.createSecureContext = function createSecureContext(options, context) {
// cert's issuer in C++ code.
if (options.ca) {
if (Array.isArray(options.ca)) {
for (i = 0; i < options.ca.length; i++) {
c.context.addCACert(options.ca[i]);
}
options.ca.forEach((ca) => {
validateKeyCert(ca, 'ca');
c.context.addCACert(ca);
});
} else {
validateKeyCert(options.ca, 'ca');
c.context.addCACert(options.ca);
}
} else {
Expand All @@ -83,9 +94,12 @@ exports.createSecureContext = function createSecureContext(options, context) {

if (options.cert) {
if (Array.isArray(options.cert)) {
for (i = 0; i < options.cert.length; i++)
c.context.setCert(options.cert[i]);
options.cert.forEach((cert) => {
validateKeyCert(cert, 'cert');
c.context.setCert(cert);
});
} else {
validateKeyCert(options.cert, 'cert');
c.context.setCert(options.cert);
}
}
Expand All @@ -96,12 +110,12 @@ exports.createSecureContext = function createSecureContext(options, context) {
// which leads to the crash later on.
if (options.key) {
if (Array.isArray(options.key)) {
for (i = 0; i < options.key.length; i++) {
const key = options.key[i];
const passphrase = key.passphrase || options.passphrase;
c.context.setKey(key.pem || key, passphrase);
}
options.key.forEach((k) => {
validateKeyCert(k.pem || k, 'key');
c.context.setKey(k.pem || k, k.passphrase || options.passphrase);
});
} else {
validateKeyCert(options.key, 'key');
c.context.setKey(options.key, options.passphrase);
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/http2.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const {
createSecureServer,
connect,
Http2ServerRequest,
Http2ServerResponse
Http2ServerResponse,
} = require('internal/http2/core');

module.exports = {
Expand All @@ -27,5 +27,5 @@ module.exports = {
createSecureServer,
connect,
Http2ServerResponse,
Http2ServerRequest
Http2ServerRequest,
};
2 changes: 1 addition & 1 deletion lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ E('ERR_ENCODING_INVALID_ENCODED_DATA',
(enc) => `The encoded data was not valid for encoding ${enc}`);
E('ERR_HTTP_HEADERS_SENT',
'Cannot %s headers after they are sent to the client');
E('ERR_HTTP_INVALID_STATUS_CODE', 'Invalid status code: %s');
E('ERR_HTTP_TRAILER_INVALID',
'Trailers are invalid with this transfer encoding');
E('ERR_HTTP_INVALID_CHAR', 'Invalid character in statusMessage.');
Expand Down Expand Up @@ -269,6 +268,7 @@ E('ERR_V8BREAKITERATOR', 'Full ICU data not installed. ' +
'See https://github.com/nodejs/node/wiki/Intl');
E('ERR_VALID_PERFORMANCE_ENTRY_TYPE',
'At least one valid performance entry type is required');
E('ERR_VALUE_OUT_OF_RANGE', 'The value of "%s" must be %s. Received "%s"');

function invalidArgType(name, expected, actual) {
assert(name, 'name is required');
Expand Down
16 changes: 9 additions & 7 deletions lib/internal/http2/compat.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,8 @@ function onStreamEnd() {
}

function onStreamError(error) {
// this is purposefully left blank
//
// errors in compatibility mode are
// not forwarded to the request
// and response objects. However,
// they are forwarded to 'clientError'
// on the server by Http2Stream
const request = this[kRequest];
request.emit('error', error);
}

function onRequestPause() {
Expand All @@ -87,6 +82,11 @@ function onStreamResponseDrain() {
response.emit('drain');
}

function onStreamResponseError(error) {
const response = this[kResponse];
response.emit('error', error);
}

function onStreamClosedRequest() {
const req = this[kRequest];
req.push(null);
Expand Down Expand Up @@ -271,7 +271,9 @@ class Http2ServerResponse extends Stream {
stream[kResponse] = this;
this.writable = true;
stream.on('drain', onStreamResponseDrain);
stream.on('error', onStreamResponseError);
stream.on('close', onStreamClosedResponse);
stream.on('aborted', onAborted.bind(this));
const onfinish = this[kFinish].bind(this);
stream.on('streamClosed', onfinish);
stream.on('finish', onfinish);
Expand Down
43 changes: 6 additions & 37 deletions lib/internal/http2/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -1506,13 +1506,6 @@ class Http2Stream extends Duplex {
this.once('ready', this._destroy.bind(this, err, callback));
return;
}

const server = session[kServer];

if (err && server) {
server.emit('streamError', err, this);
}

process.nextTick(() => {
debug(`[${sessionName(session[kType])}] destroying stream ${this[kID]}`);

Expand All @@ -1536,8 +1529,9 @@ class Http2Stream extends Duplex {
// All done
const rst = this[kState].rst;
const code = rst ? this[kState].rstCode : NGHTTP2_NO_ERROR;
if (!err && code !== NGHTTP2_NO_ERROR) {
err = new errors.Error('ERR_HTTP2_STREAM_ERROR', code);
if (code !== NGHTTP2_NO_ERROR) {
const err = new errors.Error('ERR_HTTP2_STREAM_ERROR', code);
process.nextTick(() => this.emit('error', err));
}
process.nextTick(emit.bind(this, 'streamClosed', code));
debug(`[${sessionName(session[kType])}] stream ${this[kID]} destroyed`);
Expand Down Expand Up @@ -1640,24 +1634,13 @@ function doSendFileFD(session, options, fd, headers, getTrailers, err, stat) {
abort(this);
return;
}
const onError = options.onError;

if (err) {
if (onError) {
onError(err);
} else {
this.destroy(err);
}
process.nextTick(() => this.emit('error', err));
return;
}

if (!stat.isFile()) {
err = new errors.Error('ERR_HTTP2_SEND_FILE');
if (onError) {
onError(err);
} else {
this.destroy(err);
}
process.nextTick(() => this.emit('error', err));
return;
}

Expand Down Expand Up @@ -1694,17 +1677,12 @@ function doSendFileFD(session, options, fd, headers, getTrailers, err, stat) {

function afterOpen(session, options, headers, getTrailers, err, fd) {
const state = this[kState];
const onError = options.onError;
if (this.destroyed || session.destroyed) {
abort(this);
return;
}
if (err) {
if (onError) {
onError(err);
} else {
this.destroy(err);
}
process.nextTick(() => this.emit('error', err));
return;
}
state.fd = fd;
Expand All @@ -1713,20 +1691,13 @@ function afterOpen(session, options, headers, getTrailers, err, fd) {
doSendFileFD.bind(this, session, options, fd, headers, getTrailers));
}

function streamOnError(err) {
// we swallow the error for parity with HTTP1
// all the errors that ends here are not critical for the project
debug('ServerHttp2Stream errored, avoiding uncaughtException', err);
}


class ServerHttp2Stream extends Http2Stream {
constructor(session, id, options, headers) {
super(session, options);
this[kInit](id);
this[kProtocol] = headers[HTTP2_HEADER_SCHEME];
this[kAuthority] = headers[HTTP2_HEADER_AUTHORITY];
this.on('error', streamOnError);
debug(`[${sessionName(session[kType])}] created serverhttp2stream`);
}

Expand Down Expand Up @@ -2585,8 +2556,6 @@ module.exports = {
createServer,
createSecureServer,
connect,
Http2Session,
Http2Stream,
Http2ServerRequest,
Http2ServerResponse
};
Expand Down
Loading

0 comments on commit 9a8953d

Please sign in to comment.