Comparing version 0.2.0 to 0.2.1
Version history | ||
=============== | ||
### 0.2.1 (2013-08-20) ### | ||
* Fixing a flow control bug | ||
* [Tarball](https://github.com/molnarg/node-http2/archive/node-http2-0.2.1.tar.gz) | ||
### 0.2.0 (2013-08-19) ### | ||
@@ -5,0 +10,0 @@ |
@@ -526,3 +526,3 @@ // HTTP/2 compression is implemented by two [Transform Stream][1] subclasses that operate in | ||
Compressor.header = function writeString(header) { | ||
Compressor.header = function writeHeader(header) { | ||
var representation, buffers = []; | ||
@@ -563,3 +563,3 @@ | ||
Decompressor.header = function readString(buffer) { | ||
Decompressor.header = function readHeader(buffer) { | ||
var representation, header = {}; | ||
@@ -566,0 +566,0 @@ |
@@ -159,4 +159,4 @@ var logging = require('./logging'); | ||
Connection.prototype._newStream = function _newStream(id) { | ||
this._log.trace({ stream_id: id }, 'Adding new stream.'); | ||
var stream = new Stream(this._log.child({ stream_id: id })); | ||
var stream = new Stream(this._log); | ||
this._log.debug({ s: stream.id, stream_id: id }, 'Created new stream.'); | ||
this._streamsIds[id] = stream; | ||
@@ -168,3 +168,3 @@ this.emit('new_stream', stream, id); | ||
Connection.prototype._activateStream = function _activateStream(stream) { | ||
this._log.trace({ stream_id: this._getIdOf(stream) }, 'Activating stream.'); | ||
this._log.trace({ s: stream.id }, 'Activating stream.'); | ||
this._streamPriorities.push(stream); | ||
@@ -266,3 +266,3 @@ stream.upstream.on('readable', this.read.bind(this, 0)); | ||
this._log.trace({ stream_id: id, frame: frame }, 'Trying to forward outgoing frame'); | ||
this._log.trace({ s: stream.id, frame: frame }, 'Trying to forward outgoing frame'); | ||
var moreNeeded = this._push(frame, unshiftRemainder); | ||
@@ -269,0 +269,0 @@ |
@@ -14,2 +14,5 @@ var logging = require('./logging'); | ||
// Counter for globally unique endpoint ID generation | ||
var nextId = 0; | ||
// The process of initialization: | ||
@@ -20,3 +23,4 @@ function Endpoint(role, settings, log) { | ||
// * Initializing logging infrastructure | ||
this._log = (log || logging.root).child({ component: 'endpoint' }); | ||
this.id = nextId++; | ||
this._log = (log || logging.root).child({ component: 'endpoint', e: this.id }); | ||
@@ -23,0 +27,0 @@ // * First part of the handshake process: sending and receiving the client connection header |
@@ -82,3 +82,3 @@ var assert = process.env.HTTP2_ASSERT ? require('assert') : function noop() {}; | ||
this._received = 0; | ||
this._remoteFlowControlDisabled = false; | ||
this._remoteFlowControlDisabled = true; | ||
} | ||
@@ -85,0 +85,0 @@ Flow.prototype = Object.create(Duplex.prototype, { constructor: { value: Flow } }); |
@@ -683,2 +683,6 @@ // The framer consists of two [Transform Stream][1] subclasses that operate in [object mode][2]: | ||
if (frame.promised_stream instanceof Object) { | ||
logEntry.promised_stream = 'stream-' + frame.promised_stream.id; | ||
} | ||
logEntry.flags = Object.keys(frame.flags || {}).filter(function(name) { | ||
@@ -685,0 +689,0 @@ return frame.flags[name] === true; |
140
lib/http.js
@@ -13,7 +13,13 @@ // Public API | ||
// - **Class: http2.Server** | ||
// - **Event: 'upgrade'**: upgrade is deprecated in HTTP/2 so it will never be emitted for HTTP/2 | ||
// requests. | ||
// - **Event: 'connection' (socket, [endpoint])**: there's a second argument if the negotiation of | ||
// HTTP/2 was successful: the reference to the [Endpoint](endpoint.html) object tied to the | ||
// socket. | ||
// - **Event: 'timeout'**: only emitted for HTTP/1 responses. | ||
// - **server.setTimeout(msecs, callback)**: only affects HTTP/1 connections. | ||
// - **server.timeout**: only affects HTTP/1 connections. | ||
// | ||
// - **Class: http2.ServerResponse** | ||
// - **Event: 'timeout'**: only emitted for HTTP/1 responses. | ||
// - **response.push(options)**: initiates a server push. `options` describes the 'imaginary' | ||
@@ -28,2 +34,4 @@ // request to which the push stream is a response; the possible options are identical to the | ||
// - **Class: http2.ClientRequest** | ||
// - **Event: 'upgrade'**: upgrade is deprecated in HTTP/2 so it will never be emitted for HTTP/2 | ||
// requests. | ||
// - **Event: 'socket' (socket)**: it's not emitted in case of an HTTP/2 incoming message. | ||
@@ -67,7 +75,4 @@ // - **Event: 'stream' (stream)**: in case of an HTTP/2 incoming message, a reference to the | ||
// - **Event: 'connect'** | ||
// - **Event: 'upgrade'** | ||
// - **Event: 'clientError'** | ||
// - **server.maxHeadersCount** | ||
// - **server.setTimeout(msecs, callback)** | ||
// - **server.timeout** | ||
// | ||
@@ -90,3 +95,2 @@ // - **Class: http2.ServerResponse** | ||
// - **Event: 'connect'** | ||
// - **Event: 'upgrade'** | ||
// - **Event: 'continue'** | ||
@@ -126,12 +130,6 @@ // - **request.abort()** | ||
// This should hold sane defaults. These can be overridden by the user using the options | ||
// configuration object in client and server APIs. | ||
var default_settings = { | ||
SETTINGS_MAX_CONCURRENT_STREAMS: 100 | ||
}; | ||
// IncomingMessage class | ||
// --------------------- | ||
function IncomingMessage(stream, log) { | ||
function IncomingMessage(stream) { | ||
// * This is basically a read-only wrapper for the [Stream](stream.html) class. | ||
@@ -142,3 +140,3 @@ PassThrough.call(this); | ||
this._log = log; | ||
this._log = stream._log.child({ component: 'http' }); | ||
@@ -161,7 +159,6 @@ // * HTTP/2.0 does not define a way to carry the version identifier that is included in the | ||
function OutgoingMessage(log) { | ||
function OutgoingMessage() { | ||
// * This is basically a read-only wrapper for the [Stream](stream.html) class. | ||
Writable.call(this); | ||
this._log = log; | ||
this._headers = {}; | ||
@@ -236,2 +233,3 @@ this.headersSent = false; | ||
this._log.info('Creating HTTP/2 server over TLS/NPN'); | ||
this._mode = 'tls'; | ||
options.NPNProtocols = [implementedVersion, 'http/1.1', 'http/1.0']; | ||
@@ -254,2 +252,3 @@ this._server = https.createServer(options); | ||
this._log.info('Creating HTTP/2 server over plain TCP'); | ||
this._mode = 'plain'; | ||
this._server = net.createServer(start); | ||
@@ -270,6 +269,6 @@ } | ||
Server.prototype._start = function _start(socket) { | ||
var logger = this._log.child({ client: socket.remoteAddress + ':' + socket.remotePort }); | ||
logger.info('Incoming HTTP/2 connection'); | ||
var endpoint = new Endpoint('SERVER', this._settings, this._log); | ||
var endpoint = new Endpoint('SERVER', this._settings, logger); | ||
this._log.info({ client: socket.remoteAddress + ':' + socket.remotePort, endpoint: endpoint.id }, | ||
'New incoming HTTP/2 connection'); | ||
@@ -280,4 +279,4 @@ endpoint.pipe(socket).pipe(endpoint); | ||
endpoint.on('stream', function _onStream(stream) { | ||
var response = new OutgoingResponse(endpoint, stream, logger); | ||
var request = new IncomingRequest(stream, logger); | ||
var response = new OutgoingResponse(endpoint, stream); | ||
var request = new IncomingRequest(stream); | ||
@@ -315,2 +314,33 @@ request.once('ready', self.emit.bind(self, 'request', request, response)); | ||
OutgoingRequest.prototype.setTimeout = function setTimeout(timeout, callback) { | ||
if (this._mode === 'tls') { | ||
this._server.setTimeout(timeout, callback); | ||
} | ||
}; | ||
Object.defineProperty(OutgoingRequest.prototype, 'timeout', { | ||
get: function getTimeout() { | ||
if (this._mode === 'tls') { | ||
return this._server.timeout; | ||
} | ||
}, | ||
set: function setTimeout(timeout) { | ||
if (this._mode === 'tls') { | ||
this._server.timeout = timeout; | ||
} | ||
} | ||
}); | ||
// Overriding `EventEmitter`'s `on(event, listener)` method to forward certain subscriptions to | ||
// `server`.There are events on the `http.Server` class where it makes difference whether someone is | ||
// listening on the event or not. In these cases, we can not simply forward the events from the | ||
// `server` to `this` since that means a listener. Instead, we forward the subscriptions. | ||
Server.prototype.on = function on(event, listener) { | ||
if ((event === 'upgrade') || (event === 'timeout')) { | ||
this._server.on(event, listener.bind(this)); | ||
} else { | ||
EventEmitter.prototype.on.call(this, event, listener); | ||
} | ||
}; | ||
function createServer(options, requestListener) { | ||
@@ -334,4 +364,4 @@ if (typeof options === 'function') { | ||
function IncomingRequest(stream, log) { | ||
IncomingMessage.call(this, stream, log); | ||
function IncomingRequest(stream) { | ||
IncomingMessage.call(this, stream); | ||
} | ||
@@ -407,5 +437,7 @@ IncomingRequest.prototype = Object.create(IncomingMessage.prototype, { constructor: { value: IncomingRequest } }); | ||
function OutgoingResponse(endpoint, stream, log) { | ||
OutgoingMessage.call(this, log); | ||
function OutgoingResponse(endpoint, stream) { | ||
OutgoingMessage.call(this); | ||
this._log = stream._log.child({ component: 'http' }); | ||
this.endpoint = endpoint; | ||
@@ -490,5 +522,15 @@ this.stream = stream; | ||
return new OutgoingResponse(this.endpoint, pushStream, this._log); | ||
return new OutgoingResponse(this.endpoint, pushStream); | ||
}; | ||
// Overriding `EventEmitter`'s `on(event, listener)` method to forward certain subscriptions to | ||
// `request`. See `Server.prototype.on` for explanation. | ||
OutgoingResponse.prototype.on = function on(event, listener) { | ||
if (this.request && (event === 'timeout')) { | ||
this.request.on(event, listener.bind(this)); | ||
} else { | ||
OutgoingMessage.prototype.on.call(this, event, listener); | ||
} | ||
}; | ||
// Client side | ||
@@ -543,3 +585,3 @@ // =========== | ||
var request = new OutgoingRequest(logging.root); | ||
var request = new OutgoingRequest(this._log); | ||
@@ -581,4 +623,5 @@ if (callback) { | ||
unbundleSocket(httpsRequest.socket); | ||
var logger = this._log.child({ server: options.host + ':' + options.port }); | ||
var endpoint = new Endpoint('CLIENT', this._settings, logger); | ||
var endpoint = new Endpoint('CLIENT', this._settings, this._log); | ||
this._log.info({ server: options.host + ':' + options.port, endpoint: endpoint.id }, | ||
'New incoming HTTP/2 connection'); | ||
endpoint.socket = httpsRequest.socket; | ||
@@ -637,5 +680,7 @@ endpoint.pipe(endpoint.socket).pipe(endpoint); | ||
function OutgoingRequest(log) { | ||
OutgoingMessage.call(this, log); | ||
function OutgoingRequest() { | ||
OutgoingMessage.call(this); | ||
this._log = undefined; | ||
this.socket = undefined; | ||
@@ -649,7 +694,6 @@ this.stream = undefined; | ||
OutgoingRequest.prototype._start = function _start(stream, options) { | ||
var logger = this._log.child({ server: (options.hostname || options.host) + ':' + (options.port || 80) }); | ||
logger.info('Successfully initiated HTTP/2 connection'); | ||
this.stream = stream; | ||
this._log = stream._log.child({ component: 'http' }); | ||
var headers = {}; | ||
@@ -665,4 +709,4 @@ for (var key in options.headers) { | ||
logger.info({ scheme: headers[':scheme'], method: headers[':method'], host: headers[':host'], | ||
path: headers[':path'], headers: (options.headers || {}) }, 'Sending request'); | ||
this._log.info({ scheme: headers[':scheme'], method: headers[':method'], host: headers[':host'], | ||
path: headers[':path'], headers: (options.headers || {}) }, 'Sending request'); | ||
this.stream.headers(headers); | ||
@@ -672,3 +716,3 @@ | ||
var response = new IncomingResponse(this.stream, logger); | ||
var response = new IncomingResponse(this.stream); | ||
response.once('ready', this.emit.bind(this, 'response', response)); | ||
@@ -678,4 +722,2 @@ }; | ||
OutgoingRequest.prototype._fallback = function _fallback(request) { | ||
this._log.info('Falling back to simple HTTPS'); | ||
this.request = request; | ||
@@ -688,2 +730,12 @@ this.socket = request.socket; | ||
// Overriding `EventEmitter`'s `on(event, listener)` method to forward certain subscriptions to | ||
// `request`. See `Server.prototype.on` for explanation. | ||
OutgoingRequest.prototype.on = function on(event, listener) { | ||
if (this.request && (event === 'upgrade')) { | ||
this.request.on(event, listener.bind(this)); | ||
} else { | ||
OutgoingMessage.prototype.on.call(this, event, listener); | ||
} | ||
}; | ||
// Methods only in fallback mode | ||
@@ -708,8 +760,7 @@ OutgoingRequest.prototype.setNoDelay = function setNoDelay(noDelay) { | ||
// IncomingResponse class | ||
// ---------------------- | ||
function IncomingResponse(stream, log) { | ||
IncomingMessage.call(this, stream, log); | ||
function IncomingResponse(stream) { | ||
IncomingMessage.call(this, stream); | ||
stream.on('promise', this._onPromise.bind(this)); | ||
@@ -747,3 +798,3 @@ } | ||
IncomingResponse.prototype._onPromise = function _onPromise(stream, headers) { | ||
var promise = new IncomingPromise(stream, headers, this._log); | ||
var promise = new IncomingPromise(stream, headers); | ||
@@ -760,8 +811,9 @@ if (this.listeners('push').length > 0) { | ||
function IncomingPromise(responseStream, promiseHeaders, log) { | ||
function IncomingPromise(responseStream, promiseHeaders) { | ||
var stream = new Readable(); | ||
stream._read = function noop() {}; | ||
stream.push(null); | ||
stream._log = responseStream._log; | ||
IncomingRequest.call(this, stream, log); | ||
IncomingRequest.call(this, stream); | ||
@@ -772,3 +824,3 @@ stream.emit('headers', promiseHeaders); | ||
var response = new IncomingResponse(this._responseStream, log); | ||
var response = new IncomingResponse(this._responseStream); | ||
response.once('ready', this.emit.bind(this, 'response', response)); | ||
@@ -775,0 +827,0 @@ } |
@@ -35,2 +35,4 @@ var assert = process.env.HTTP2_ASSERT ? require('assert') : function noop() {}; | ||
// | ||
// * **id**: a globally unique, public ID for easier logging | ||
// | ||
// Headers are always in the [regular node.js header format][1]. | ||
@@ -42,2 +44,5 @@ // [1]: http://nodejs.org/api/http.html#http_message_headers | ||
// Counter for globally unique stream ID generation | ||
var nextId = 0; | ||
// The main aspects of managing the stream are: | ||
@@ -47,4 +52,5 @@ function Stream(log) { | ||
// * every method uses the common logger object | ||
this._log = (log || logging.root).child({ component: 'stream' }); | ||
// * logging | ||
this.id = nextId++; | ||
this._log = (log || logging.root).child({ component: 'stream', s: this.id }); | ||
@@ -51,0 +57,0 @@ // * receiving and sending stream management commands |
{ | ||
"name": "http2", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "An HTTP/2 server implementation", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
node-http2 | ||
========== | ||
An HTTP/2 server implementation for node.js, developed as a [Google Summer of Code project] | ||
(https://google-melange.appspot.com/gsoc/project/google/gsoc2013/molnarg/5001). | ||
An HTTP/2 server implementation for node.js, developed as a [Google Summer of Code | ||
project](https://google-melange.appspot.com/gsoc/project/google/gsoc2013/molnarg/5001). | ||
@@ -21,3 +21,3 @@ Installation | ||
Detailed API documentation is primarily maintained in the `lib/http.js` file and is [available in | ||
the wiki](wiki/node-http2-API) as well. | ||
the wiki](https://github.com/molnarg/node-http2/wiki/Public-API) as well. | ||
@@ -77,3 +77,4 @@ Examples | ||
For a server push example, see the source code of the example | ||
[server](blob/master/example/server.js) and [client](blob/master/example/client.js). | ||
[server](https://github.com/molnarg/node-http2/blob/master/example/server.js) and | ||
[client](https://github.com/molnarg/node-http2/blob/master/example/client.js). | ||
@@ -80,0 +81,0 @@ Status |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
939727
5108
167