Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

spdy

Package Overview
Dependencies
Maintainers
4
Versions
206
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

spdy - npm Package Compare versions

Comparing version 3.4.4 to 3.4.5

26

lib/spdy.js

@@ -1,20 +0,20 @@

'use strict';
'use strict'
var spdy = exports;
var spdy = exports
// Export tools
spdy.handle = require('./spdy/handle');
spdy.request = require('./spdy/request');
spdy.response = require('./spdy/response');
spdy.Socket = require('./spdy/socket');
spdy.handle = require('./spdy/handle')
spdy.request = require('./spdy/request')
spdy.response = require('./spdy/response')
spdy.Socket = require('./spdy/socket')
// Export client
spdy.agent = require('./spdy/agent');
spdy.Agent = spdy.agent.Agent;
spdy.createAgent = spdy.agent.create;
spdy.agent = require('./spdy/agent')
spdy.Agent = spdy.agent.Agent
spdy.createAgent = spdy.agent.create
// Export server
spdy.server = require('./spdy/server');
spdy.Server = spdy.server.Server;
spdy.PlainServer = spdy.server.PlainServer;
spdy.createServer = spdy.server.create;
spdy.server = require('./spdy/server')
spdy.Server = spdy.server.Server
spdy.PlainServer = spdy.server.PlainServer
spdy.createServer = spdy.server.create

@@ -1,87 +0,93 @@

'use strict';
'use strict'
var assert = require('assert');
var http = require('http');
var https = require('https');
var net = require('net');
var util = require('util');
var transport = require('spdy-transport');
var debug = require('debug')('spdy:client');
var assert = require('assert')
var http = require('http')
var https = require('https')
var net = require('net')
var util = require('util')
var transport = require('spdy-transport')
var debug = require('debug')('spdy:client')
var EventEmitter = require('events').EventEmitter;
var EventEmitter = require('events').EventEmitter
var spdy = require('../spdy');
var spdy = require('../spdy')
var mode = /^v0\.8\./.test(process.version) ? 'rusty' :
/^v0\.(9|10)\./.test(process.version) ? 'old' :
/^v0\.12\./.test(process.version) ? 'normal' :
'modern';
var mode = /^v0\.8\./.test(process.version)
? 'rusty'
: /^v0\.(9|10)\./.test(process.version)
? 'old'
: /^v0\.12\./.test(process.version)
? 'normal'
: 'modern'
var proto = {};
var proto = {}
function instantiate(base) {
function Agent(options) {
this._init(base, options);
function instantiate (base) {
function Agent (options) {
this._init(base, options)
}
util.inherits(Agent, base);
util.inherits(Agent, base)
Agent.create = function create(options) {
return new Agent(options);
};
Agent.create = function create (options) {
return new Agent(options)
}
Object.keys(proto).forEach(function(key) {
Agent.prototype[key] = proto[key];
});
Object.keys(proto).forEach(function (key) {
Agent.prototype[key] = proto[key]
})
return Agent;
return Agent
}
proto._init = function _init(base, options) {
base.call(this, options);
proto._init = function _init (base, options) {
base.call(this, options)
var state = {};
this._spdyState = state;
var state = {}
this._spdyState = state
state.host = options.host;
state.options = options.spdy || {};
state.secure = this instanceof https.Agent;
state.fallback = false;
state.createSocket = this._getCreateSocket();
state.socket = null;
state.connection = null;
state.host = options.host
state.options = options.spdy || {}
state.secure = this instanceof https.Agent
state.fallback = false
state.createSocket = this._getCreateSocket()
state.socket = null
state.connection = null
// No chunked encoding
this.keepAlive = false;
this.keepAlive = false
var self = this;
this._connect(options, function(err, connection) {
if (err)
return self.emit('error', err);
var self = this
this._connect(options, function (err, connection) {
if (err) {
return self.emit('error', err)
}
state.connection = connection;
self.emit('_connect');
});
};
state.connection = connection
self.emit('_connect')
})
}
proto._getCreateSocket = function _getCreateSocket() {
proto._getCreateSocket = function _getCreateSocket () {
// Find super's `createSocket` method
var createSocket;
var cons = this.constructor.super_;
var createSocket
var cons = this.constructor.super_
do {
createSocket = cons.prototype.createSocket;
createSocket = cons.prototype.createSocket
if (cons.super_ === EventEmitter || !cons.super_)
break;
cons = cons.super_;
} while (!createSocket);
if (!createSocket)
createSocket = http.Agent.prototype.createSocket;
if (cons.super_ === EventEmitter || !cons.super_) {
break
}
cons = cons.super_
} while (!createSocket)
if (!createSocket) {
createSocket = http.Agent.prototype.createSocket
}
assert(createSocket, '.createSocket() method not found');
assert(createSocket, '.createSocket() method not found')
return createSocket;
};
return createSocket
}
proto._connect = function _connect(options, callback) {
var state = this._spdyState;
proto._connect = function _connect (options, callback) {
var state = this._spdyState

@@ -92,3 +98,3 @@ var protocols = state.options.protocols || [

'http/1.1', 'http/1.0'
];
]

@@ -100,22 +106,22 @@ // TODO(indutny): reconnect automatically?

servername: options.servername || options.host
}, options));
state.socket = socket;
}, options))
state.socket = socket
socket.setNoDelay(true);
socket.setNoDelay(true)
function onError(err) {
return callback(err);
function onError (err) {
return callback(err)
}
socket.on('error', onError);
socket.on('error', onError)
socket.on(state.secure ? 'secureConnect' : 'connect', function() {
socket.removeListener('error', onError);
socket.on(state.secure ? 'secureConnect' : 'connect', function () {
socket.removeListener('error', onError)
var protocol;
var protocol
if (state.secure) {
protocol = socket.npnProtocol ||
socket.alpnProtocol ||
state.options.protocol;
state.options.protocol
} else {
protocol = state.options.protocol;
protocol = state.options.protocol
}

@@ -125,42 +131,42 @@

if (!protocol || protocol === 'http/1.1' || protocol === 'http/1.0') {
debug('activating fallback');
socket.destroy();
state.fallback = true;
return;
debug('activating fallback')
socket.destroy()
state.fallback = true
return
}
debug('connected protocol=%j', protocol);
debug('connected protocol=%j', protocol)
var connection = transport.connection.create(socket, util._extend({
protocol: /spdy/.test(protocol) ? 'spdy' : 'http2',
isServer: false
}, state.options.connection || {}));
}, state.options.connection || {}))
// Set version when we are certain
if (protocol === 'h2') {
connection.start(4);
connection.start(4)
} else if (protocol === 'spdy/3.1') {
connection.start(3.1);
connection.start(3.1)
} else if (protocol === 'spdy/3') {
connection.start(3);
connection.start(3)
} else if (protocol === 'spdy/2') {
connection.start(2);
connection.start(2)
} else {
socket.destroy();
callback(new Error('Unexpected protocol: ' + protocol));
return;
socket.destroy()
callback(new Error('Unexpected protocol: ' + protocol))
return
}
if (state.options['x-forwarded-for'] !== undefined)
connection.sendXForwardedFor(state.options['x-forwarded-for']);
if (state.options['x-forwarded-for'] !== undefined) {
connection.sendXForwardedFor(state.options['x-forwarded-for'])
}
callback(null, connection);
});
};
callback(null, connection)
})
}
proto._createSocket = function _createSocket(req, options, callback) {
var state = this._spdyState;
if (state.fallback)
return state.createSocket(req, options);
proto._createSocket = function _createSocket (req, options, callback) {
var state = this._spdyState
if (state.fallback) { return state.createSocket(req, options) }
var handle = spdy.handle.create(null, null, state.socket);
var handle = spdy.handle.create(null, null, state.socket)

@@ -170,51 +176,54 @@ var socketOptions = {

allowHalfOpen: true
};
}
var socket;
if (state.secure)
socket = new spdy.Socket(state.socket, socketOptions);
else
socket = new net.Socket(socketOptions);
var socket
if (state.secure) {
socket = new spdy.Socket(state.socket, socketOptions)
} else {
socket = new net.Socket(socketOptions)
}
handle.assignSocket(socket);
handle.assignClientRequest(req);
handle.assignSocket(socket)
handle.assignClientRequest(req)
// Create stream only once `req.end()` is called
var self = this;
handle.once('needStream', function() {
var self = this
handle.once('needStream', function () {
if (state.connection === null) {
self.once('_connect', function() {
handle.setStream(self._createStream(req, handle));
});
self.once('_connect', function () {
handle.setStream(self._createStream(req, handle))
})
} else {
handle.setStream(self._createStream(req, handle));
handle.setStream(self._createStream(req, handle))
}
});
})
// Yes, it is in reverse
req.on('response', function(res) {
handle.assignRequest(res);
});
handle.assignResponse(req);
req.on('response', function (res) {
handle.assignRequest(res)
})
handle.assignResponse(req)
// Handle PUSH
req.addListener('newListener', spdy.request.onNewListener);
req.addListener('newListener', spdy.request.onNewListener)
// For v0.8
socket.readable = true;
socket.writable = true;
socket.readable = true
socket.writable = true
if (callback)
return callback(null, socket);
if (callback) {
return callback(null, socket)
}
return socket;
};
return socket
}
if (mode === 'modern' || mode === 'normal') {
proto.createSocket = proto._createSocket;
proto.createSocket = proto._createSocket
} else {
proto.createSocket = function createSocket(name, host, port, addr, req) {
var state = this._spdyState;
if (state.fallback)
return state.createSocket(name, host, port, addr, req);
proto.createSocket = function createSocket (name, host, port, addr, req) {
var state = this._spdyState
if (state.fallback) {
return state.createSocket(name, host, port, addr, req)
}

@@ -224,10 +233,10 @@ return this._createSocket(req, {

port: port
});
};
})
}
}
proto._createStream = function _createStream(req, handle) {
var state = this._spdyState;
proto._createStream = function _createStream (req, handle) {
var state = this._spdyState
var self = this;
var self = this
return state.connection.reserveStream({

@@ -238,43 +247,44 @@ method: req.method,

host: state.host
}, function(err, stream) {
if (err)
return self.emit('error', err);
}, function (err, stream) {
if (err) {
return self.emit('error', err)
}
stream.on('response', function(status, headers) {
handle.emitResponse(status, headers);
});
});
};
stream.on('response', function (status, headers) {
handle.emitResponse(status, headers)
})
})
}
// Public APIs
proto.close = function close(callback) {
var state = this._spdyState;
proto.close = function close (callback) {
var state = this._spdyState
if (state.connection === null) {
this.once('_connect', function() {
this.close(callback);
});
return;
this.once('_connect', function () {
this.close(callback)
})
return
}
state.connection.end(callback);
};
state.connection.end(callback)
}
exports.Agent = instantiate(https.Agent);
exports.PlainAgent = instantiate(http.Agent);
exports.Agent = instantiate(https.Agent)
exports.PlainAgent = instantiate(http.Agent)
exports.create = function create(base, options) {
exports.create = function create (base, options) {
if (typeof base === 'object') {
options = base;
base = null;
options = base
base = null
}
if (base)
return instantiate(base).create(options);
if (base) {
return instantiate(base).create(options)
}
if (options.spdy && options.spdy.plain)
return exports.PlainAgent.create(options);
else
return exports.Agent.create(options);
};
if (options.spdy && options.spdy.plain) {
return exports.PlainAgent.create(options)
} else { return exports.Agent.create(options) }
}

@@ -1,55 +0,56 @@

'use strict';
'use strict'
var assert = require('assert');
var thing = require('handle-thing');
var httpDeceiver = require('http-deceiver');
var util = require('util');
var assert = require('assert')
var thing = require('handle-thing')
var httpDeceiver = require('http-deceiver')
var util = require('util')
function Handle(options, stream, socket) {
var state = {};
this._spdyState = state;
function Handle (options, stream, socket) {
var state = {}
this._spdyState = state
state.options = options || {};
state.options = options || {}
state.stream = stream;
state.socket = null;
state.rawSocket = socket || stream.connection.socket;
state.deceiver = null;
state.ending = false;
state.stream = stream
state.socket = null
state.rawSocket = socket || stream.connection.socket
state.deceiver = null
state.ending = false
var self = this;
var self = this
thing.call(this, stream, {
getPeerName: function() {
return self._getPeerName();
getPeerName: function () {
return self._getPeerName()
},
close: function(callback) {
return self._closeCallback(callback);
close: function (callback) {
return self._closeCallback(callback)
}
});
})
if (!state.stream) {
this.on('stream', function(stream) {
state.stream = stream;
});
this.on('stream', function (stream) {
state.stream = stream
})
}
}
util.inherits(Handle, thing);
module.exports = Handle;
util.inherits(Handle, thing)
module.exports = Handle
Handle.create = function create(options, stream, socket) {
return new Handle(options, stream, socket);
};
Handle.create = function create (options, stream, socket) {
return new Handle(options, stream, socket)
}
Handle.prototype._getPeerName = function _getPeerName() {
var state = this._spdyState;
Handle.prototype._getPeerName = function _getPeerName () {
var state = this._spdyState
if (state.rawSocket._getpeername)
return state.rawSocket._getpeername();
if (state.rawSocket._getpeername) {
return state.rawSocket._getpeername()
}
return null;
};
return null
}
Handle.prototype._closeCallback = function _closeCallback(callback) {
var state = this._spdyState;
var stream = state.stream;
Handle.prototype._closeCallback = function _closeCallback (callback) {
var state = this._spdyState
var stream = state.stream

@@ -68,154 +69,158 @@ if (state.ending) {

// `end` on UV_EOF. This results in aborted request without `end` event.
setImmediate(callback);
setImmediate(callback)
} else if (stream._writableState.ending) {
stream.once('finish', function() {
callback(null);
});
stream.once('finish', function () {
callback(null)
})
} else {
stream.end(callback);
stream.end(callback)
}
} else {
stream.abort(callback);
stream.abort(callback)
}
// Only a single end is allowed
state.ending = false;
};
state.ending = false
}
Handle.prototype.getStream = function getStream(callback) {
var state = this._spdyState;
Handle.prototype.getStream = function getStream (callback) {
var state = this._spdyState
if (!callback) {
assert(state.stream);
return state.stream;
assert(state.stream)
return state.stream
}
if (state.stream) {
process.nextTick(function() {
callback(state.stream);
});
return;
process.nextTick(function () {
callback(state.stream)
})
return
}
this.on('stream', callback);
};
this.on('stream', callback)
}
Handle.prototype.assignSocket = function assignSocket(socket, options) {
var state = this._spdyState;
Handle.prototype.assignSocket = function assignSocket (socket, options) {
var state = this._spdyState
state.socket = socket;
state.deceiver = httpDeceiver.create(socket, options);
state.socket = socket
state.deceiver = httpDeceiver.create(socket, options)
function onStreamError(err) {
state.socket.emit('error', err);
function onStreamError (err) {
state.socket.emit('error', err)
}
this.getStream(function(stream) {
stream.on('error', onStreamError);
});
};
this.getStream(function (stream) {
stream.on('error', onStreamError)
})
}
Handle.prototype.assignClientRequest = function assignClientRequest(req) {
var state = this._spdyState;
var oldEnd = req.end;
var oldSend = req._send;
Handle.prototype.assignClientRequest = function assignClientRequest (req) {
var state = this._spdyState
var oldEnd = req.end
var oldSend = req._send
// Catch the headers before request will be sent
var self = this;
var self = this
// For old nodes
if (thing.mode !== 'modern') {
req.end = function end() {
this.end = oldEnd;
req.end = function end () {
this.end = oldEnd
this._send('');
this._send('')
return this.end.apply(this, arguments);
};
return this.end.apply(this, arguments)
}
}
req._send = function send(data) {
this._headerSent = true;
req._send = function send (data) {
this._headerSent = true
// for v0.10 and below, otherwise it will set `hot = false` and include
// headers in first write
this._header = 'ignore me';
this._header = 'ignore me'
// To prevent exception
this.connection = state.socket;
this.connection = state.socket
// It is very important to leave this here, otherwise it will be executed
// on a next tick, after `_send` will perform write
self.getStream(function(stream) {
stream.send();
});
self.getStream(function (stream) {
stream.send()
})
// We are ready to create stream
self.emit('needStream');
self.emit('needStream')
req._send = oldSend;
req._send = oldSend
// Ignore empty writes
if (req.method === 'GET' && data.length === 0)
return;
if (req.method === 'GET' && data.length === 0) {
return
}
return req._send.apply(this, arguments);
};
return req._send.apply(this, arguments)
}
// No chunked encoding
req.useChunkedEncodingByDefault = false;
req.useChunkedEncodingByDefault = false
req.on('finish', function() {
req.socket.end();
});
};
req.on('finish', function () {
req.socket.end()
})
}
Handle.prototype.assignRequest = function assignRequest(req) {
Handle.prototype.assignRequest = function assignRequest (req) {
// Emit trailing headers
this.getStream(function(stream) {
stream.on('headers', function(headers) {
req.emit('trailers', headers);
});
});
};
this.getStream(function (stream) {
stream.on('headers', function (headers) {
req.emit('trailers', headers)
})
})
}
Handle.prototype.assignResponse = function assignResponse(res) {
var self = this;
Handle.prototype.assignResponse = function assignResponse (res) {
var self = this
res.addTrailers = function addTrailers(headers) {
self.getStream(function(stream) {
stream.sendHeaders(headers);
});
};
};
res.addTrailers = function addTrailers (headers) {
self.getStream(function (stream) {
stream.sendHeaders(headers)
})
}
}
Handle.prototype._transformHeaders = function _transformHeaders(kind, headers) {
var state = this._spdyState;
Handle.prototype._transformHeaders = function _transformHeaders (kind, headers) {
var state = this._spdyState
var res = {};
var keys = Object.keys(headers);
var res = {}
var keys = Object.keys(headers)
if (kind === 'request' && state.options['x-forwarded-for']) {
var xforwarded = state.stream.connection.getXForwardedFor();
if (xforwarded !== null)
res['x-forwarded-for'] = xforwarded;
var xforwarded = state.stream.connection.getXForwardedFor()
if (xforwarded !== null) {
res['x-forwarded-for'] = xforwarded
}
}
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var value = headers[key];
var key = keys[i]
var value = headers[key]
if (key === ':authority')
res.host = value;
if (/^:/.test(key))
continue;
if (key === ':authority') {
res.host = value
}
if (/^:/.test(key)) {
continue
}
res[key] = value;
res[key] = value
}
return res;
};
return res
}
Handle.prototype.emitRequest = function emitRequest() {
var state = this._spdyState;
var stream = state.stream;
Handle.prototype.emitRequest = function emitRequest () {
var state = this._spdyState
var stream = state.stream

@@ -226,7 +231,7 @@ state.deceiver.emitRequest({

headers: this._transformHeaders('request', stream.headers)
});
};
})
}
Handle.prototype.emitResponse = function emitResponse(status, headers) {
var state = this._spdyState;
Handle.prototype.emitResponse = function emitResponse (status, headers) {
var state = this._spdyState

@@ -236,3 +241,3 @@ state.deceiver.emitResponse({

headers: this._transformHeaders('response', headers)
});
};
})
}

@@ -1,31 +0,33 @@

'use strict';
'use strict'
function attachPush(req) {
var handle = req.socket._handle;
function attachPush (req) {
var handle = req.socket._handle
handle.getStream(function(stream) {
stream.on('pushPromise', function(push) {
req.emit('push', push);
});
});
handle.getStream(function (stream) {
stream.on('pushPromise', function (push) {
req.emit('push', push)
})
})
}
exports.onNewListener = function onNewListener(type) {
var req = this;
exports.onNewListener = function onNewListener (type) {
var req = this
if (type !== 'push')
return;
if (type !== 'push') {
return
}
// Not first listener
if (req.listeners('push').length !== 0)
return;
if (req.listeners('push').length !== 0) {
return
}
if (!req.socket) {
req.on('socket', function() {
attachPush(req);
});
return;
req.on('socket', function () {
attachPush(req)
})
return
}
attachPush(req);
};
attachPush(req)
}

@@ -1,17 +0,17 @@

'use strict';
'use strict'
// NOTE: Mostly copy paste from node
exports.writeHead = function writeHead(statusCode, reason, obj) {
var headers;
exports.writeHead = function writeHead (statusCode, reason, obj) {
var headers
if (typeof reason === 'string') {
// writeHead(statusCode, reasonPhrase[, headers])
this.statusMessage = reason;
this.statusMessage = reason
} else {
// writeHead(statusCode[, headers])
this.statusMessage =
this.statusMessage || 'unknown';
obj = reason;
this.statusMessage || 'unknown'
obj = reason
}
this.statusCode = statusCode;
this.statusCode = statusCode

@@ -21,17 +21,17 @@ if (this._headers) {

if (obj) {
var keys = Object.keys(obj);
var keys = Object.keys(obj)
for (var i = 0; i < keys.length; i++) {
var k = keys[i];
if (k) this.setHeader(k, obj[k]);
var k = keys[i]
if (k) this.setHeader(k, obj[k])
}
}
// only progressive api is used
headers = this._renderHeaders();
headers = this._renderHeaders()
} else {
// only writeHead() called
headers = obj;
headers = obj
}
if (statusCode === 204 || statusCode === 304 ||
(100 <= statusCode && statusCode <= 199)) {
(statusCode >= 100 && statusCode <= 199)) {
// RFC 2616, 10.2.5:

@@ -47,3 +47,3 @@ // The 204 response MUST NOT include a message-body, and thus is always

// terminated by an empty line.
this._hasBody = false;
this._hasBody = false
}

@@ -54,32 +54,33 @@

if (this._expect_continue && !this._sent100) {
this.shouldKeepAlive = false;
this.shouldKeepAlive = false
}
// Implicit headers sent!
this._header = true;
this._headerSent = true;
this._header = true
this._headerSent = true
if (this.socket._handle)
this.socket._handle._spdyState.stream.respond(this.statusCode, headers);
};
if (this.socket._handle) { this.socket._handle._spdyState.stream.respond(this.statusCode, headers) }
}
exports.end = function end(data, encoding, callback) {
if (!this._headerSent)
this.writeHead(this.statusCode);
exports.end = function end (data, encoding, callback) {
if (!this._headerSent) {
this.writeHead(this.statusCode)
}
if (!this.socket._handle)
return;
if (!this.socket._handle) {
return
}
// Compatibility with Node.js core
this.finished = true;
this.finished = true
var self = this;
var handle = this.socket._handle;
handle._spdyState.ending = true;
this.socket.end(data, encoding, function() {
self.constructor.prototype.end.call(self, '', 'utf8', callback);
});
};
var self = this
var handle = this.socket._handle
handle._spdyState.ending = true
this.socket.end(data, encoding, function () {
self.constructor.prototype.end.call(self, '', 'utf8', callback)
})
}
exports.push = function push(path, headers, callback) {
exports.push = function push (path, headers, callback) {
var frame = {

@@ -92,11 +93,12 @@ path: path,

response: headers.response
};
}
var stream = this.spdyStream;
return stream.pushPromise(frame, callback);
};
var stream = this.spdyStream
return stream.pushPromise(frame, callback)
}
exports.writeContinue = function writeContinue(callback) {
if (this.socket._handle)
this.socket._handle._spdyState.stream.respond(100, {}, callback);
};
exports.writeContinue = function writeContinue (callback) {
if (this.socket._handle) {
this.socket._handle._spdyState.stream.respond(100, {}, callback)
}
}

@@ -1,40 +0,40 @@

'use strict';
'use strict'
var assert = require('assert');
var https = require('https');
var http = require('http');
var tls = require('tls');
var net = require('net');
var util = require('util');
var selectHose = require('select-hose');
var transport = require('spdy-transport');
var debug = require('debug')('spdy:server');
var EventEmitter = require('events').EventEmitter;
var assert = require('assert')
var https = require('https')
var http = require('http')
var tls = require('tls')
var net = require('net')
var util = require('util')
var selectHose = require('select-hose')
var transport = require('spdy-transport')
var debug = require('debug')('spdy:server')
var EventEmitter = require('events').EventEmitter
var spdy = require('../spdy');
var spdy = require('../spdy')
var proto = {};
var proto = {}
function instantiate(base) {
function Server(options, handler) {
this._init(base, options, handler);
function instantiate (base) {
function Server (options, handler) {
this._init(base, options, handler)
}
util.inherits(Server, base);
util.inherits(Server, base)
Server.create = function create(options, handler) {
return new Server(options, handler);
};
Server.create = function create (options, handler) {
return new Server(options, handler)
}
Object.keys(proto).forEach(function(key) {
Server.prototype[key] = proto[key];
});
Object.keys(proto).forEach(function (key) {
Server.prototype[key] = proto[key]
})
return Server;
return Server
}
proto._init = function _init(base, options, handler) {
var state = {};
this._spdyState = state;
proto._init = function _init (base, options, handler) {
var state = {}
this._spdyState = state
state.options = options.spdy || {};
state.options = options.spdy || {}

@@ -45,3 +45,3 @@ var protocols = state.options.protocols || [

'http/1.1', 'http/1.0'
];
]

@@ -53,56 +53,59 @@ var actualOptions = util._extend({

ALPNProtocols: protocols
}, options);
}, options)
state.secure = this instanceof tls.Server;
state.secure = this instanceof tls.Server
if (state.secure)
base.call(this, actualOptions);
else
base.call(this);
if (state.secure) {
base.call(this, actualOptions)
} else {
base.call(this)
}
// Support HEADERS+FIN
this.httpAllowHalfOpen = true;
this.httpAllowHalfOpen = true
var event = state.secure ? 'secureConnection' : 'connection';
var event = state.secure ? 'secureConnection' : 'connection'
state.listeners = this.listeners(event).slice();
assert(state.listeners.length > 0, 'Server does not have default listeners');
this.removeAllListeners(event);
state.listeners = this.listeners(event).slice()
assert(state.listeners.length > 0, 'Server does not have default listeners')
this.removeAllListeners(event)
if (state.options.plain)
this.on(event, this._onPlainConnection);
else
this.on(event, this._onConnection);
if (state.options.plain) {
this.on(event, this._onPlainConnection)
} else { this.on(event, this._onConnection) }
if (handler)
this.on('request', handler);
if (handler) {
this.on('request', handler)
}
debug('server init secure=%d', state.secure);
};
debug('server init secure=%d', state.secure)
}
proto._onConnection = function _onConnection(socket) {
var state = this._spdyState;
proto._onConnection = function _onConnection (socket) {
var state = this._spdyState
var protocol;
if (state.secure)
protocol = socket.npnProtocol || socket.alpnProtocol;
var protocol
if (state.secure) {
protocol = socket.npnProtocol || socket.alpnProtocol
}
this._handleConnection(socket, protocol);
};
this._handleConnection(socket, protocol)
}
proto._handleConnection = function _handleConnection(socket, protocol) {
var state = this._spdyState;
proto._handleConnection = function _handleConnection (socket, protocol) {
var state = this._spdyState
if (!protocol)
protocol = state.options.protocol;
if (!protocol) {
protocol = state.options.protocol
}
debug('incoming socket protocol=%j', protocol);
debug('incoming socket protocol=%j', protocol)
// No way we can do anything with the socket
if (!protocol || protocol === 'http/1.1' || protocol === 'http/1.0') {
debug('to default handler it goes');
return this._invokeDefault(socket);
debug('to default handler it goes')
return this._invokeDefault(socket)
}
socket.setNoDelay(true);
socket.setNoDelay(true)

@@ -112,73 +115,68 @@ var connection = transport.connection.create(socket, util._extend({

isServer: true
}, state.options.connection || {}));
}, state.options.connection || {}))
// Set version when we are certain
if (protocol === 'http2')
connection.start(4);
else if (protocol === 'spdy/3.1')
connection.start(3.1);
else if (protocol === 'spdy/3')
connection.start(3);
else if (protocol === 'spdy/2')
connection.start(2);
if (protocol === 'http2') { connection.start(4) } else if (protocol === 'spdy/3.1') {
connection.start(3.1)
} else if (protocol === 'spdy/3') { connection.start(3) } else if (protocol === 'spdy/2') {
connection.start(2)
}
connection.on('error', function() {
socket.destroy();
});
connection.on('error', function () {
socket.destroy()
})
var self = this;
connection.on('stream', function(stream) {
self._onStream(stream);
});
};
var self = this
connection.on('stream', function (stream) {
self._onStream(stream)
})
}
// HTTP2 preface
var PREFACE = 'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n';
var PREFACE_BUFFER = new Buffer(PREFACE);
var PREFACE = 'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'
var PREFACE_BUFFER = new Buffer(PREFACE)
function hoseFilter(data, callback) {
if (data.length < 1)
return callback(null, null);
function hoseFilter (data, callback) {
if (data.length < 1) {
return callback(null, null)
}
// SPDY!
if (data[0] === 0x80)
return callback(null, 'spdy');
if (data[0] === 0x80) { return callback(null, 'spdy') }
var avail = Math.min(data.length, PREFACE_BUFFER.length);
for (var i = 0; i < avail; i++)
if (data[i] !== PREFACE_BUFFER[i])
return callback(null, 'http/1.1');
var avail = Math.min(data.length, PREFACE_BUFFER.length)
for (var i = 0; i < avail; i++) {
if (data[i] !== PREFACE_BUFFER[i]) { return callback(null, 'http/1.1') }
}
// Not enough bytes to be sure about HTTP2
if (avail !== PREFACE_BUFFER.length)
return callback(null, null);
if (avail !== PREFACE_BUFFER.length) { return callback(null, null) }
return callback(null, 'h2');
return callback(null, 'h2')
}
proto._onPlainConnection = function _onPlainConnection(socket) {
var hose = selectHose.create(socket, {}, hoseFilter);
proto._onPlainConnection = function _onPlainConnection (socket) {
var hose = selectHose.create(socket, {}, hoseFilter)
var self = this;
hose.on('select', function(protocol, socket) {
self._handleConnection(socket, protocol);
});
var self = this
hose.on('select', function (protocol, socket) {
self._handleConnection(socket, protocol)
})
hose.on('error', function(err) {
debug('hose error %j', err.message);
socket.destroy();
});
};
hose.on('error', function (err) {
debug('hose error %j', err.message)
socket.destroy()
})
}
proto._invokeDefault = function _invokeDefault(socket) {
var state = this._spdyState;
proto._invokeDefault = function _invokeDefault (socket) {
var state = this._spdyState
for (var i = 0; i < state.listeners.length; i++)
state.listeners[i].call(this, socket);
};
for (var i = 0; i < state.listeners.length; i++) { state.listeners[i].call(this, socket) }
}
proto._onStream = function _onStream(stream) {
var state = this._spdyState;
proto._onStream = function _onStream (stream) {
var state = this._spdyState
var handle = spdy.handle.create(this._spdyState.options, stream);
var handle = spdy.handle.create(this._spdyState.options, stream)

@@ -188,17 +186,26 @@ var socketOptions = {

allowHalfOpen: true
};
}
var socket;
if (state.secure)
socket = new spdy.Socket(stream.connection.socket, socketOptions);
else
socket = new net.Socket(socketOptions);
var socket
if (state.secure) {
socket = new spdy.Socket(stream.connection.socket, socketOptions)
} else {
socket = new net.Socket(socketOptions)
}
handle.assignSocket(socket);
// This is needed because the `error` listener, added by the default
// `connection` listener, no longer has bound arguments. It relies instead
// on the `server` property of the socket. See https://github.com/nodejs/node/pull/11926
// for more details.
// This is only done for Node.js >= 4 in order to not break compatibility
// with older versions of the platform.
if (process.versions.modules >= 46) { socket.server = this }
handle.assignSocket(socket)
// For v0.8
socket.readable = true;
socket.writable = true;
socket.readable = true
socket.writable = true
this._invokeDefault(socket);
this._invokeDefault(socket)

@@ -210,65 +217,66 @@ // Add lazy `checkContinue` listener, otherwise `res.writeContinue` will be

EventEmitter.listenerCount(this, 'checkContinue') === 0) {
this.once('checkContinue', function(req, res) {
res.writeContinue();
this.once('checkContinue', function (req, res) {
res.writeContinue()
this.emit('request', req, res);
});
this.emit('request', req, res)
})
}
handle.emitRequest();
};
handle.emitRequest()
}
proto.emit = function emit(event, req, res) {
if (event !== 'request' && event !== 'checkContinue')
return EventEmitter.prototype.emit.apply(this, arguments);
proto.emit = function emit (event, req, res) {
if (event !== 'request' && event !== 'checkContinue') {
return EventEmitter.prototype.emit.apply(this, arguments)
}
if (!(req.socket._handle instanceof spdy.handle)) {
debug('not spdy req/res');
req.isSpdy = false;
req.spdyVersion = 1;
res.isSpdy = false;
res.spdyVersion = 1;
return EventEmitter.prototype.emit.apply(this, arguments);
debug('not spdy req/res')
req.isSpdy = false
req.spdyVersion = 1
res.isSpdy = false
res.spdyVersion = 1
return EventEmitter.prototype.emit.apply(this, arguments)
}
var handle = req.connection._handle;
var handle = req.connection._handle
req.isSpdy = true;
req.spdyVersion = handle.getStream().connection.getVersion();
res.isSpdy = true;
res.spdyVersion = req.spdyVersion;
req.spdyStream = handle.getStream();
req.isSpdy = true
req.spdyVersion = handle.getStream().connection.getVersion()
res.isSpdy = true
res.spdyVersion = req.spdyVersion
req.spdyStream = handle.getStream()
debug('override req/res');
res.writeHead = spdy.response.writeHead;
res.end = spdy.response.end;
res.push = spdy.response.push;
res.writeContinue = spdy.response.writeContinue;
res.spdyStream = handle.getStream();
debug('override req/res')
res.writeHead = spdy.response.writeHead
res.end = spdy.response.end
res.push = spdy.response.push
res.writeContinue = spdy.response.writeContinue
res.spdyStream = handle.getStream()
res._req = req;
res._req = req
handle.assignRequest(req);
handle.assignResponse(res);
handle.assignRequest(req)
handle.assignResponse(res)
return EventEmitter.prototype.emit.apply(this, arguments);
};
return EventEmitter.prototype.emit.apply(this, arguments)
}
exports.Server = instantiate(https.Server);
exports.PlainServer = instantiate(http.Server);
exports.Server = instantiate(https.Server)
exports.PlainServer = instantiate(http.Server)
exports.create = function create(base, options, handler) {
exports.create = function create (base, options, handler) {
if (typeof base === 'object') {
handler = options;
options = base;
base = null;
handler = options
options = base
base = null
}
if (base)
return instantiate(base).create(options, handler);
if (base) {
return instantiate(base).create(options, handler)
}
if (options.spdy && options.spdy.plain)
return exports.PlainServer.create(options, handler);
else
return exports.Server.create(options, handler);
};
if (options.spdy && options.spdy.plain) { return exports.PlainServer.create(options, handler) } else {
return exports.Server.create(options, handler)
}
}

@@ -1,25 +0,25 @@

'use strict';
'use strict'
var util = require('util');
var net = require('net');
var util = require('util')
var net = require('net')
function Socket(parent, options) {
net.Socket.call(this, options);
function Socket (parent, options) {
net.Socket.call(this, options)
var state = {};
var state = {}
this._spdyState = state;
this._spdyState = state
state.parent = parent;
state.parent = parent
this.servername = parent.servername;
this.npnProtocol = parent.npnProtocol;
this.alpnProtocol = parent.alpnProtocol;
this.authorized = parent.authorized;
this.authorizationError = parent.authorizationError;
this.encrypted = true;
this.servername = parent.servername
this.npnProtocol = parent.npnProtocol
this.alpnProtocol = parent.alpnProtocol
this.authorized = parent.authorized
this.authorizationError = parent.authorizationError
this.encrypted = true
}
util.inherits(Socket, net.Socket);
util.inherits(Socket, net.Socket)
module.exports = Socket;
module.exports = Socket

@@ -30,9 +30,9 @@ var methods = [

'getCipher', 'getEphemeralKeyInfo'
];
]
methods.forEach(function(method) {
Socket.prototype[method] = function methodWrap() {
var parent = this._spdyState.parent;
return parent[method].apply(parent, arguments);
};
});
methods.forEach(function (method) {
Socket.prototype[method] = function methodWrap () {
var parent = this._spdyState.parent
return parent[method].apply(parent, arguments)
}
})
{
"name": "spdy",
"version": "3.4.4",
"version": "3.4.5",
"description": "Implementation of the SPDY protocol on node.js.",
"license": "MIT",
"scripts": {
"lint": "standard",
"test": "mocha --reporter=spec test/*-test.js",
"coverage": "istanbul cover node_modules/.bin/_mocha -- --reporter=spec test/**/*-test.js"
},
"pre-commit": [
"lint",
"test"
],
"keywords": [

@@ -16,3 +25,3 @@ "spdy"

"email": "node-spdy+bugs@indutny.com",
"url": "https://github.com/indutny/node-spdy/issues"
"url": "https://github.com/spdy-http2/node-spdy/issues"
},

@@ -36,9 +45,7 @@ "author": "Fedor Indutny <fedor.indutny@gmail.com>",

"devDependencies": {
"jscs": "^1.13.1",
"jshint": "^2.8.0",
"mocha": "^2.2.x"
"istanbul": "^0.4.5",
"mocha": "^2.2.x",
"pre-commit": "^1.2.2",
"standard": "^8.6.0"
},
"scripts": {
"test": "jscs lib/**/*.js test/*.js && jshint lib/**/*.js && mocha --reporter=spec test/*-test.js"
},
"engines": [

@@ -45,0 +52,0 @@ "node >= 0.7.0"

# SPDY Server for node.js
[![Build Status](https://travis-ci.org/indutny/node-spdy.svg?branch=master)](https://travis-ci.org/indutny/node-spdy)
[![NPM version](https://badge.fury.io/js/spdy.svg)](http://badge.fury.io/js/spdy)
[![Build Status](https://travis-ci.org/spdy-http2/node-spdy.svg?branch=master)](http://travis-ci.org/spdy-http2/node-spdy)
[![NPM version](https://badge.fury.io/js/node-spdy.svg)](http://badge.fury.io/js/node-spdy)
[![dependencies Status](https://david-dm.org/spdy-http2/node-spdy/status.svg?style=flat-square)](https://david-dm.org/spdy-http2/node-spdy)
[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square)](http://standardjs.com/)
[![Waffle](https://img.shields.io/badge/track-waffle-blue.svg?style=flat-square)](https://waffle.io/spdy-http2/node-spdy)

@@ -14,2 +17,4 @@ With this module you can create [HTTP2][0] / [SPDY][1] servers

### Examples
Server:

@@ -59,3 +64,3 @@ ```javascript

var spdy = require('spdy');
var http = require('http');
var https = require('https');

@@ -68,4 +73,4 @@ var agent = spdy.createAgent({

spdy: {
plain: false or true,
ssl: false or true,
plain: false,
ssl: true,

@@ -77,3 +82,3 @@ // **optional** send X_FORWARDED_FOR

http.get({
https.get({
host: 'www.google.com',

@@ -104,24 +109,4 @@ agent: agent

## API
#### Push streams
API is compatible with `http` and `https` module, but you can use another
function as base class for SPDYServer.
```javascript
spdy.createServer(
[base class constructor, i.e. https.Server],
{ /* keys and options */ }, // <- the only one required argument
[request listener]
).listen([port], [host], [callback]);
```
Request listener will receive two arguments: `request` and `response`. They're
both instances of `http`'s `IncomingMessage` and `OutgoingMessage`. But three
custom properties are added to both of them: `isSpdy`, `spdyVersion`. `isSpdy`
is `true` when the request was processed using HTTP2/SPDY protocols, it is
`false` in case of HTTP/1.1 fallback. `spdyVersion` is either of: `2`, `3`,
`3.1`, or `4` (for HTTP2).
### Push streams
It is possible to initiate [PUSH_PROMISE][5] to send content to clients _before_

@@ -179,3 +164,3 @@ the client requests it.

### Trailing headers
#### Trailing headers

@@ -208,3 +193,3 @@ Server usage:

### Options
#### Options

@@ -228,2 +213,23 @@ All options supported by [tls][2] work with node-spdy.

### API
API is compatible with `http` and `https` module, but you can use another
function as base class for SPDYServer.
```javascript
spdy.createServer(
[base class constructor, i.e. https.Server],
{ /* keys and options */ }, // <- the only one required argument
[request listener]
).listen([port], [host], [callback]);
```
Request listener will receive two arguments: `request` and `response`. They're
both instances of `http`'s `IncomingMessage` and `OutgoingMessage`. But three
custom properties are added to both of them: `isSpdy`, `spdyVersion`. `isSpdy`
is `true` when the request was processed using HTTP2/SPDY protocols, it is
`false` in case of HTTP/1.1 fallback. `spdyVersion` is either of: `2`, `3`,
`3.1`, or `4` (for HTTP2).
#### Contributors

@@ -230,0 +236,0 @@

@@ -1,20 +0,21 @@

var assert = require('assert');
var https = require('https');
var http = require('http');
var util = require('util');
var transport = require('spdy-transport');
/* eslint-env mocha */
var fixtures = require('./fixtures');
var spdy = require('../');
var assert = require('assert')
var https = require('https')
var http = require('http')
var util = require('util')
describe('SPDY Client', function() {
describe('regular', function() {
fixtures.everyConfig(function(protocol, npn, version, plain) {
var server;
var agent;
var hmodule;
var fixtures = require('./fixtures')
var spdy = require('../')
beforeEach(function(done) {
hmodule = plain ? http : https;
describe('SPDY Client', function () {
describe('regular', function () {
fixtures.everyConfig(function (protocol, npn, version, plain) {
var server
var agent
var hmodule
beforeEach(function (done) {
hmodule = plain ? http : https
var options = util._extend({

@@ -24,11 +25,11 @@ spdy: {

}
}, fixtures.keys);
server = spdy.createServer(options, function(req, res) {
var body = '';
req.on('data', function(chunk) {
body += chunk;
});
req.on('end', function() {
res.writeHead(200, req.headers);
res.addTrailers({ trai: 'ler' });
}, fixtures.keys)
server = spdy.createServer(options, function (req, res) {
var body = ''
req.on('data', function (chunk) {
body += chunk
})
req.on('end', function () {
res.writeHead(200, req.headers)
res.addTrailers({ trai: 'ler' })

@@ -39,15 +40,15 @@ var push = res.push('/push', {

}
}, function(err) {
assert(!err);
}, function (err) {
assert(!err)
push.end('push');
push.on('error', function() {
});
push.end('push')
push.on('error', function () {
})
res.end(body || 'okay');
});
});
});
res.end(body || 'okay')
})
})
})
server.listen(fixtures.port, function() {
server.listen(fixtures.port, function () {
agent = spdy.createAgent({

@@ -61,20 +62,21 @@ rejectUnauthorized: false,

}
});
})
done();
});
});
done()
})
})
afterEach(function(done) {
var waiting = 2;
agent.close(next);
server.close(next);
afterEach(function (done) {
var waiting = 2
agent.close(next)
server.close(next)
function next() {
if (--waiting === 0)
done();
function next () {
if (--waiting === 0) {
done()
}
}
});
})
it('should send GET request', function(done) {
it('should send GET request', function (done) {
var req = hmodule.request({

@@ -88,12 +90,12 @@ agent: agent,

}
}, function(res) {
assert.equal(res.statusCode, 200);
assert.equal(res.headers.a, 'b');
}, function (res) {
assert.equal(res.statusCode, 200)
assert.equal(res.headers.a, 'b')
fixtures.expectData(res, 'okay', done);
});
req.end();
});
fixtures.expectData(res, 'okay', done)
})
req.end()
})
it('should send POST request', function(done) {
it('should send POST request', function (done) {
var req = hmodule.request({

@@ -108,16 +110,16 @@ agent: agent,

}
}, function(res) {
assert.equal(res.statusCode, 200);
assert.equal(res.headers.post, 'headers');
}, function (res) {
assert.equal(res.statusCode, 200)
assert.equal(res.headers.post, 'headers')
fixtures.expectData(res, 'post body', done);
});
fixtures.expectData(res, 'post body', done)
})
agent._spdyState.socket.once(plain ? 'connect' : 'secureConnect',
function() {
req.end('post body');
});
});
function () {
req.end('post body')
})
})
it('should receive PUSH_PROMISE', function(done) {
it('should receive PUSH_PROMISE', function (done) {
var req = hmodule.request({

@@ -128,18 +130,18 @@ agent: agent,

path: '/get'
}, function(res) {
assert.equal(res.statusCode, 200);
}, function (res) {
assert.equal(res.statusCode, 200)
res.resume();
});
req.on('push', function(push) {
assert.equal(push.path, '/push');
assert.equal(push.headers.push, 'yes');
res.resume()
})
req.on('push', function (push) {
assert.equal(push.path, '/push')
assert.equal(push.headers.push, 'yes')
push.resume();
push.once('end', done);
});
req.end();
});
push.resume()
push.once('end', done)
})
req.end()
})
it('should receive trailing headers', function(done) {
it('should receive trailing headers', function (done) {
var req = hmodule.request({

@@ -150,23 +152,23 @@ agent: agent,

path: '/get'
}, function(res) {
assert.equal(res.statusCode, 200);
}, function (res) {
assert.equal(res.statusCode, 200)
res.on('trailers', function(headers) {
assert.equal(headers.trai, 'ler');
fixtures.expectData(res, 'okay', done);
});
});
req.end();
});
});
});
res.on('trailers', function (headers) {
assert.equal(headers.trai, 'ler')
fixtures.expectData(res, 'okay', done)
})
})
req.end()
})
})
})
describe('x-forwarded-for', function() {
fixtures.everyConfig(function(protocol, npn, version, plain) {
var server;
var agent;
var hmodule;
describe('x-forwarded-for', function () {
fixtures.everyConfig(function (protocol, npn, version, plain) {
var server
var agent
var hmodule
beforeEach(function(done) {
hmodule = plain ? http : https;
beforeEach(function (done) {
hmodule = plain ? http : https

@@ -178,9 +180,9 @@ var options = util._extend({

}
}, fixtures.keys);
server = spdy.createServer(options, function(req, res) {
res.writeHead(200, req.headers);
res.end();
});
}, fixtures.keys)
server = spdy.createServer(options, function (req, res) {
res.writeHead(200, req.headers)
res.end()
})
server.listen(fixtures.port, function() {
server.listen(fixtures.port, function () {
agent = spdy.createAgent({

@@ -195,20 +197,21 @@ rejectUnauthorized: false,

}
});
})
done();
});
});
done()
})
})
afterEach(function(done) {
var waiting = 2;
agent.close(next);
server.close(next);
afterEach(function (done) {
var waiting = 2
agent.close(next)
server.close(next)
function next() {
if (--waiting === 0)
done();
function next () {
if (--waiting === 0) {
done()
}
}
});
})
it('should send x-forwarded-for', function(done) {
it('should send x-forwarded-for', function (done) {
var req = hmodule.request({

@@ -219,13 +222,13 @@ agent: agent,

path: '/get'
}, function(res) {
assert.equal(res.statusCode, 200);
assert.equal(res.headers['x-forwarded-for'], '1.2.3.4');
}, function (res) {
assert.equal(res.statusCode, 200)
assert.equal(res.headers['x-forwarded-for'], '1.2.3.4')
res.resume();
res.once('end', done);
});
req.end();
});
});
});
});
res.resume()
res.once('end', done)
})
req.end()
})
})
})
})

@@ -1,6 +0,7 @@

'use strict';
/* eslint-env mocha */
'use strict'
var assert = require('assert');
var assert = require('assert')
exports.port = 23433;
exports.port = 23433

@@ -52,18 +53,18 @@ exports.keys = {

'-----END CERTIFICATE-----'
};
}
function expectData(stream, expected, callback) {
var actual = '';
function expectData (stream, expected, callback) {
var actual = ''
stream.on('data', function(chunk) {
actual += chunk;
});
stream.on('end', function() {
assert.equal(actual, expected);
callback();
});
stream.on('data', function (chunk) {
actual += chunk
})
stream.on('end', function () {
assert.equal(actual, expected)
callback()
})
}
exports.expectData = expectData;
exports.expectData = expectData
exports.everyProtocol = function everyProtocol(body) {
exports.everyProtocol = function everyProtocol (body) {
var protocols = [

@@ -74,23 +75,24 @@ { protocol: 'http2', npn: 'h2', version: 4 },

{ protocol: 'spdy', npn: 'spdy/2', version: 2 }
];
]
protocols.forEach(function(protocol) {
describe(protocol.npn, function() {
body(protocol.protocol, protocol.npn, protocol.version);
});
});
};
protocols.forEach(function (protocol) {
describe(protocol.npn, function () {
body(protocol.protocol, protocol.npn, protocol.version)
})
})
}
exports.everyConfig = function everyConfig(body) {
exports.everyProtocol(function(protocol, npn, version) {
if (npn === 'spdy/2')
return;
exports.everyConfig = function everyConfig (body) {
exports.everyProtocol(function (protocol, npn, version) {
if (npn === 'spdy/2') {
return
}
[ false, true ].forEach(function(plain) {
describe(plain ? 'plain mode' : 'ssl mode', function() {
body(protocol, npn, version, plain);
});
});
});
[ false, true ].forEach(function (plain) {
describe(plain ? 'plain mode' : 'ssl mode', function () {
body(protocol, npn, version, plain)
})
})
})
}

@@ -1,17 +0,19 @@

var assert = require('assert');
var tls = require('tls');
var net = require('net');
var https = require('https');
var transport = require('spdy-transport');
var util = require('util');
/* eslint-env mocha */
var fixtures = require('./fixtures');
var spdy = require('../');
var assert = require('assert')
var tls = require('tls')
var net = require('net')
var https = require('https')
var transport = require('spdy-transport')
var util = require('util')
describe('SPDY Server', function() {
fixtures.everyConfig(function(protocol, npn, version, plain) {
var server;
var client;
var fixtures = require('./fixtures')
var spdy = require('../')
beforeEach(function(done) {
describe('SPDY Server', function () {
fixtures.everyConfig(function (protocol, npn, version, plain) {
var server
var client
beforeEach(function (done) {
server = spdy.createServer(util._extend({

@@ -22,5 +24,5 @@ spdy: {

}
}, fixtures.keys));
}, fixtures.keys))
server.listen(fixtures.port, function() {
server.listen(fixtures.port, function () {
var socket = (plain ? net : tls).connect({

@@ -30,19 +32,19 @@ rejectUnauthorized: false,

NPNProtocols: [ npn ]
}, function() {
}, function () {
client = transport.connection.create(socket, {
protocol: protocol,
isServer: false
});
client.start(version);
done();
});
});
});
})
client.start(version)
done()
})
})
})
afterEach(function(done) {
client.socket.destroy();
server.close(done);
});
afterEach(function (done) {
client.socket.destroy()
server.close(done)
})
it('should process GET request', function(done) {
it('should process GET request', function (done) {
var stream = client.request({

@@ -54,84 +56,86 @@ method: 'GET',

}
}, function(err) {
assert(!err);
}, function (err) {
assert(!err)
stream.on('response', function(status, headers) {
assert.equal(status, 200);
assert.equal(headers.ok, 'yes');
stream.on('response', function (status, headers) {
assert.equal(status, 200)
assert.equal(headers.ok, 'yes')
fixtures.expectData(stream, 'response', done);
});
fixtures.expectData(stream, 'response', done)
})
stream.end();
});
stream.end()
})
server.on('request', function(req, res) {
assert.equal(req.isSpdy, res.isSpdy);
assert.equal(req.spdyVersion, res.spdyVersion);
assert(req.isSpdy);
server.on('request', function (req, res) {
assert.equal(req.isSpdy, res.isSpdy)
assert.equal(req.spdyVersion, res.spdyVersion)
assert(req.isSpdy)
if (!plain) {
assert(req.socket.encrypted);
assert(req.socket.getPeerCertificate());
assert(req.socket.encrypted)
assert(req.socket.getPeerCertificate())
}
// Auto-detection
if (version === 3.1)
assert(req.spdyVersion >= 3 && req.spdyVersion <= 3.1);
else
assert.equal(req.spdyVersion, version);
assert(req.spdyStream);
assert(res.spdyStream);
if (version === 3.1) {
assert(req.spdyVersion >= 3 && req.spdyVersion <= 3.1)
} else {
assert.equal(req.spdyVersion, version)
}
assert(req.spdyStream)
assert(res.spdyStream)
assert.equal(req.method, 'GET');
assert.equal(req.url, '/get');
assert.deepEqual(req.headers, { a: 'b', host: 'localhost' });
assert.equal(req.method, 'GET')
assert.equal(req.url, '/get')
assert.deepEqual(req.headers, { a: 'b', host: 'localhost' })
req.on('end', function() {
req.on('end', function () {
res.writeHead(200, {
ok: 'yes'
});
res.end('response');
assert(res.finished, 'res.finished should be set');
});
req.resume();
});
});
})
res.end('response')
assert(res.finished, 'res.finished should be set')
})
req.resume()
})
})
it('should process POST request', function(done) {
it('should process POST request', function (done) {
var stream = client.request({
method: 'POST',
path: '/post'
}, function(err) {
assert(!err);
}, function (err) {
assert(!err)
stream.on('response', function(status, headers) {
assert.equal(status, 200);
assert.equal(headers.ok, 'yes');
stream.on('response', function (status, headers) {
assert.equal(status, 200)
assert.equal(headers.ok, 'yes')
fixtures.expectData(stream, 'response', next);
});
fixtures.expectData(stream, 'response', next)
})
stream.end('request');
});
stream.end('request')
})
server.on('request', function(req, res) {
assert.equal(req.method, 'POST');
assert.equal(req.url, '/post');
server.on('request', function (req, res) {
assert.equal(req.method, 'POST')
assert.equal(req.url, '/post')
res.writeHead(200, {
ok: 'yes'
});
res.end('response');
})
res.end('response')
fixtures.expectData(req, 'request', next);
});
fixtures.expectData(req, 'request', next)
})
var waiting = 2;
function next() {
if (--waiting === 0)
return done();
var waiting = 2
function next () {
if (--waiting === 0) {
return done()
}
}
});
})
it('should process expect-continue request', function(done) {
it('should process expect-continue request', function (done) {
var stream = client.request({

@@ -143,23 +147,23 @@ method: 'GET',

}
}, function(err) {
assert(!err);
}, function (err) {
assert(!err)
stream.on('response', function(status, headers) {
assert.equal(status, 100);
stream.on('response', function (status, headers) {
assert.equal(status, 100)
fixtures.expectData(stream, 'response', done);
});
fixtures.expectData(stream, 'response', done)
})
stream.end();
});
stream.end()
})
server.on('request', function(req, res) {
req.on('end', function() {
res.end('response');
});
req.resume();
});
});
server.on('request', function (req, res) {
req.on('end', function () {
res.end('response')
})
req.resume()
})
})
it('should emit `checkContinue` request', function(done) {
it('should emit `checkContinue` request', function (done) {
var stream = client.request({

@@ -171,48 +175,48 @@ method: 'GET',

}
}, function(err) {
assert(!err);
}, function (err) {
assert(!err)
stream.on('response', function(status, headers) {
assert.equal(status, 100);
stream.on('response', function (status, headers) {
assert.equal(status, 100)
fixtures.expectData(stream, 'response', done);
});
fixtures.expectData(stream, 'response', done)
})
stream.end();
});
stream.end()
})
server.on('checkContinue', function(req, res) {
req.on('end', function() {
res.writeContinue();
res.end('response');
});
req.resume();
});
});
server.on('checkContinue', function (req, res) {
req.on('end', function () {
res.writeContinue()
res.end('response')
})
req.resume()
})
})
it('should send PUSH_PROMISE', function(done) {
it('should send PUSH_PROMISE', function (done) {
var stream = client.request({
method: 'POST',
path: '/page'
}, function(err) {
assert(!err);
}, function (err) {
assert(!err)
stream.on('pushPromise', function(push) {
assert.equal(push.path, '/push');
assert.equal(push.headers.yes, 'push');
stream.on('pushPromise', function (push) {
assert.equal(push.path, '/push')
assert.equal(push.headers.yes, 'push')
fixtures.expectData(push, 'push', next);
fixtures.expectData(stream, 'response', next);
});
fixtures.expectData(push, 'push', next)
fixtures.expectData(stream, 'response', next)
})
stream.end('request');
});
stream.end('request')
})
server.on('request', function(req, res) {
assert.equal(req.method, 'POST');
assert.equal(req.url, '/page');
server.on('request', function (req, res) {
assert.equal(req.method, 'POST')
assert.equal(req.url, '/page')
res.writeHead(200, {
ok: 'yes'
});
})

@@ -223,157 +227,158 @@ var push = res.push('/push', {

}
});
push.end('push');
})
push.end('push')
res.end('response');
res.end('response')
fixtures.expectData(req, 'request', next);
});
fixtures.expectData(req, 'request', next)
})
var waiting = 3;
function next() {
if (--waiting === 0)
return done();
var waiting = 3
function next () {
if (--waiting === 0) {
return done()
}
}
});
})
it('should receive trailing headers', function(done) {
it('should receive trailing headers', function (done) {
var stream = client.request({
method: 'POST',
path: '/post'
}, function(err) {
assert(!err);
}, function (err) {
assert(!err)
stream.sendHeaders({ trai: 'ler' });
stream.end();
stream.sendHeaders({ trai: 'ler' })
stream.end()
stream.on('response', function(status, headers) {
assert.equal(status, 200);
assert.equal(headers.ok, 'yes');
stream.on('response', function (status, headers) {
assert.equal(status, 200)
assert.equal(headers.ok, 'yes')
fixtures.expectData(stream, 'response', done);
});
});
fixtures.expectData(stream, 'response', done)
})
})
server.on('request', function(req, res) {
var gotHeaders = false;
req.on('trailers', function(headers) {
gotHeaders = true;
assert.equal(headers.trai, 'ler');
});
server.on('request', function (req, res) {
var gotHeaders = false
req.on('trailers', function (headers) {
gotHeaders = true
assert.equal(headers.trai, 'ler')
})
req.on('end', function() {
assert(gotHeaders);
req.on('end', function () {
assert(gotHeaders)
res.writeHead(200, {
ok: 'yes'
});
res.end('response');
});
req.resume();
});
});
})
res.end('response')
})
req.resume()
})
})
it('should call .writeHead() automatically', function(done) {
it('should call .writeHead() automatically', function (done) {
var stream = client.request({
method: 'POST',
path: '/post'
}, function(err) {
assert(!err);
}, function (err) {
assert(!err)
stream.on('response', function(status, headers) {
assert.equal(status, 300);
stream.on('response', function (status, headers) {
assert.equal(status, 300)
fixtures.expectData(stream, 'response', done);
});
stream.end();
});
fixtures.expectData(stream, 'response', done)
})
stream.end()
})
server.on('request', function(req, res) {
req.on('end', function() {
res.statusCode = 300;
res.end('response');
});
req.resume();
});
});
server.on('request', function (req, res) {
req.on('end', function () {
res.statusCode = 300
res.end('response')
})
req.resume()
})
})
it('should not crash on .writeHead() after socket close', function(done) {
it('should not crash on .writeHead() after socket close', function (done) {
var stream = client.request({
method: 'POST',
path: '/post'
}, function(err) {
assert(!err);
}, function (err) {
assert(!err)
setTimeout(function() {
client.socket.destroy();
}, 50);
stream.on('error', function() {});
stream.end();
});
setTimeout(function () {
client.socket.destroy()
}, 50)
stream.on('error', function () {})
stream.end()
})
server.on('request', function(req, res) {
req.connection.on('close', function() {
assert.doesNotThrow(function() {
res.writeHead(200);
res.end('response');
});
done();
});
});
});
server.on('request', function (req, res) {
req.connection.on('close', function () {
assert.doesNotThrow(function () {
res.writeHead(200)
res.end('response')
})
done()
})
})
})
it('should not crash on .push() after socket close', function(done) {
it('should not crash on .push() after socket close', function (done) {
var stream = client.request({
method: 'POST',
path: '/post'
}, function(err) {
assert(!err);
}, function (err) {
assert(!err)
setTimeout(function() {
client.socket.destroy();
}, 50);
stream.on('error', function() {});
stream.end();
});
setTimeout(function () {
client.socket.destroy()
}, 50)
stream.on('error', function () {})
stream.end()
})
server.on('request', function(req, res) {
req.connection.on('close', function() {
assert.doesNotThrow(function() {
assert.equal(res.push('/push', {}), undefined);
res.end('response');
});
done();
});
});
});
server.on('request', function (req, res) {
req.connection.on('close', function () {
assert.doesNotThrow(function () {
assert.equal(res.push('/push', {}), undefined)
res.end('response')
})
done()
})
})
})
it('should end response after writing everything down', function(done) {
it('should end response after writing everything down', function (done) {
var stream = client.request({
method: 'GET',
path: '/post'
}, function(err) {
assert(!err);
}, function (err) {
assert(!err)
stream.on('response', function(status, headers) {
assert.equal(status, 200);
stream.on('response', function (status, headers) {
assert.equal(status, 200)
fixtures.expectData(stream, 'hello world, what\'s up?', done);
});
fixtures.expectData(stream, 'hello world, what\'s up?', done)
})
stream.end();
});
stream.end()
})
server.on('request', function(req, res) {
req.resume();
res.writeHead(200);
res.write('hello ');
res.write('world');
res.write(', what\'s');
res.write(' up?');
res.end();
});
});
server.on('request', function (req, res) {
req.resume()
res.writeHead(200)
res.write('hello ')
res.write('world')
res.write(', what\'s')
res.write(' up?')
res.end()
})
})
it('should handle x-forwarded-for', function(done) {
client.sendXForwardedFor('1.2.3.4');
it('should handle x-forwarded-for', function (done) {
client.sendXForwardedFor('1.2.3.4')

@@ -383,50 +388,49 @@ var stream = client.request({

path: '/post'
}, function(err) {
assert(!err);
}, function (err) {
assert(!err)
stream.resume();
stream.on('end', done);
stream.end();
});
stream.resume()
stream.on('end', done)
stream.end()
})
server.on('request', function(req, res) {
assert.equal(req.headers['x-forwarded-for'], '1.2.3.4');
req.resume();
res.end();
});
});
server.on('request', function (req, res) {
assert.equal(req.headers['x-forwarded-for'], '1.2.3.4')
req.resume()
res.end()
})
})
it('should destroy request after end', function(done) {
it('should destroy request after end', function (done) {
var stream = client.request({
method: 'POST',
path: '/post'
}, function(err) {
assert(!err);
});
stream.end();
stream.on('error', function() {});
}, function (err) {
assert(!err)
})
stream.end()
stream.on('error', function () {})
server.on('request', function(req, res) {
res.end();
res.destroy();
res.socket.on('close', function() {
done();
});
});
});
server.on('request', function (req, res) {
res.end()
res.destroy()
res.socket.on('close', function () {
done()
})
})
})
})
});
it('should respond to http/1.1', function (done) {
var server = spdy.createServer(fixtures.keys, function (req, res) {
assert.equal(req.isSpdy, res.isSpdy)
assert.equal(req.spdyVersion, res.spdyVersion)
assert(!req.isSpdy)
assert.equal(req.spdyVersion, 1)
it('should respond to http/1.1', function(done) {
var server = spdy.createServer(fixtures.keys, function(req, res) {
assert.equal(req.isSpdy, res.isSpdy);
assert.equal(req.spdyVersion, res.spdyVersion);
assert(!req.isSpdy);
assert.equal(req.spdyVersion, 1);
res.writeHead(200)
res.end()
})
res.writeHead(200);
res.end();
});
server.listen(fixtures.port, function() {
server.listen(fixtures.port, function () {
var req = https.request({

@@ -439,31 +443,31 @@ agent: false,

path: '/'
}, function(res) {
assert.equal(res.statusCode, 200);
res.resume();
res.on('end', function() {
server.close(done);
});
});
}, function (res) {
assert.equal(res.statusCode, 200)
res.resume()
res.on('end', function () {
server.close(done)
})
})
req.end();
});
});
req.end()
})
})
it('should support custom base', function(done) {
function Pseuver(options, listener) {
https.Server.call(this, options, listener);
it('should support custom base', function (done) {
function Pseuver (options, listener) {
https.Server.call(this, options, listener)
}
util.inherits(Pseuver, https.Server);
util.inherits(Pseuver, https.Server)
var server = spdy.createServer(Pseuver, fixtures.keys, function(req, res) {
assert.equal(req.isSpdy, res.isSpdy);
assert.equal(req.spdyVersion, res.spdyVersion);
assert(!req.isSpdy);
assert.equal(req.spdyVersion, 1);
var server = spdy.createServer(Pseuver, fixtures.keys, function (req, res) {
assert.equal(req.isSpdy, res.isSpdy)
assert.equal(req.spdyVersion, res.spdyVersion)
assert(!req.isSpdy)
assert.equal(req.spdyVersion, 1)
res.writeHead(200);
res.end();
});
res.writeHead(200)
res.end()
})
server.listen(fixtures.port, function() {
server.listen(fixtures.port, function () {
var req = https.request({

@@ -476,13 +480,13 @@ agent: false,

path: '/'
}, function(res) {
assert.equal(res.statusCode, 200);
res.resume();
res.on('end', function() {
server.close(done);
});
});
}, function (res) {
assert.equal(res.statusCode, 200)
res.resume()
res.on('end', function () {
server.close(done)
})
})
req.end();
});
});
});
req.end()
})
})
})

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc