michael@0: var assert = require('assert'), michael@0: spdy = require('../../'), michael@0: keys = require('../fixtures/keys'), michael@0: https = require('https'), michael@0: tls = require('tls'),request michael@0: Buffer = require('buffer').Buffer; michael@0: michael@0: suite('A SPDY Server', function() { michael@0: var server; michael@0: setup(function(done) { michael@0: server = spdy.createServer(keys, function(req, res) { michael@0: res.end('ok'); michael@0: }); michael@0: michael@0: server.listen(8081, done); michael@0: }); michael@0: michael@0: teardown(function(done) { michael@0: server.once('close', done); michael@0: server.close(); michael@0: }); michael@0: michael@0: test('should respond on regular https requests', function(done) { michael@0: https.request({ michael@0: host: 'localhost', michael@0: port: 8081, michael@0: path: '/', michael@0: method: 'GET', michael@0: agent: false, michael@0: rejectUnauthorized: false michael@0: }, function(res) { michael@0: assert.equal(res.statusCode, 200); michael@0: done(); michael@0: }).end(); michael@0: }); michael@0: michael@0: test('should respond on spdy requests', function(done) { michael@0: var socket = tls.connect( michael@0: 8081, michael@0: 'localhost', michael@0: { NPNProtocols: ['spdy/2'], rejectUnauthorized: false }, michael@0: function() { michael@0: var deflate = spdy.utils.createDeflate(2), michael@0: chunks = [], michael@0: length = 0; michael@0: michael@0: deflate.on('data', function(chunk) { michael@0: chunks.push(chunk); michael@0: length += chunk.length; michael@0: }); michael@0: michael@0: // Deflate headers michael@0: deflate.write(new Buffer([ michael@0: 0x00, 0x04, // method, url, version = 3 fields michael@0: 0x00, 0x06, michael@0: 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // method michael@0: 0x00, 0x03, michael@0: 0x47, 0x45, 0x54, // get michael@0: 0x00, 0x03, michael@0: 0x75, 0x72, 0x6c, // url michael@0: 0x00, 0x01, michael@0: 0x2f, // '/' michael@0: 0x00, 0x07, michael@0: 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, // version michael@0: 0x00, 0x08, michael@0: 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, // HTTP/1.1 michael@0: 0x00, 0x04, michael@0: 0x68, 0x6f, 0x73, 0x74, // host michael@0: 0x00, 0x09, michael@0: 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74 //localhost michael@0: ])); michael@0: michael@0: deflate.flush(function() { michael@0: // StreamID + Associated StreamID michael@0: length += 10; michael@0: michael@0: // Headers michael@0: socket.write(new Buffer([ michael@0: 0x80, 0x02, 0x00, 0x01, // Control, Version, SYN_STREAM michael@0: 0x00, 0x00, 0x00, length, // Flags, length (1 byte in this case) michael@0: 0x00, 0x00, 0x00, 0x01, // StreamID michael@0: 0x00, 0x00, 0x00, 0x00, // Associated StreamID michael@0: 0x00, 0x00 // Priority + Unused michael@0: ])); michael@0: michael@0: // Write compressed headers michael@0: chunks.forEach(function(chunk) { michael@0: socket.write(chunk); michael@0: }); michael@0: }); michael@0: michael@0: var response = new Buffer(85), michael@0: offset = 0; michael@0: michael@0: socket.on('data', function(chunk) { michael@0: assert.ok(offset + chunk.length <= 85); michael@0: michael@0: chunk.copy(response, offset); michael@0: offset += chunk.length; michael@0: michael@0: if (offset === 85) { michael@0: var frames = []; michael@0: michael@0: offset = 0; michael@0: while (offset < response.length) { michael@0: var len = (response.readUInt32BE(offset + 4) & 0x00ffffff) + 8; michael@0: frames.push(response.slice(offset, offset + len)); michael@0: michael@0: offset += len; michael@0: } michael@0: michael@0: // SYN_STREAM frame michael@0: assert.ok(frames.some(function(frame) { michael@0: return frame[0] === 0x80 && // Control frame michael@0: frame[1] === 0x02 && // Version michael@0: frame.readUInt16BE(2) === 0x0002 && // SYN_STREAM michael@0: frame.readUInt32BE(8) === 0x0001; // StreamID michael@0: })); michael@0: michael@0: // Data frames michael@0: assert.ok(frames.some(function(frame) { michael@0: return frame[0] === 0x00 && // Data frame michael@0: frame.readUInt32BE(0) === 0x0001 && // StreamID michael@0: frame.slice(8).toString() === 'ok'; michael@0: })); michael@0: michael@0: socket.destroy(); michael@0: } michael@0: }); michael@0: michael@0: socket.on('close', function() { michael@0: done(); michael@0: }); michael@0: } michael@0: ); michael@0: michael@0: socket.on('error', function(err) { michael@0: console.error('Socket error: ' + err); michael@0: }); michael@0: michael@0: server.on('request', function(req, res) { michael@0: assert.equal(req.url, '/'); michael@0: assert.equal(req.method, 'GET'); michael@0: res.end('ok'); michael@0: }); michael@0: }); michael@0: });