You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
487 lines
12 KiB
487 lines
12 KiB
/* eslint-env mocha */ |
|
|
|
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') |
|
|
|
var fixtures = require('./fixtures') |
|
var spdy = require('../') |
|
|
|
describe('SPDY Server', function () { |
|
fixtures.everyConfig(function (protocol, alpn, version, plain) { |
|
var server |
|
var client |
|
|
|
beforeEach(function (done) { |
|
server = spdy.createServer(Object.assign({ |
|
spdy: { |
|
'x-forwarded-for': true, |
|
plain: plain |
|
} |
|
}, fixtures.keys)) |
|
|
|
server.listen(fixtures.port, function () { |
|
var socket = (plain ? net : tls).connect({ |
|
rejectUnauthorized: false, |
|
port: fixtures.port, |
|
ALPNProtocols: [alpn] |
|
}, function () { |
|
client = transport.connection.create(socket, { |
|
protocol: protocol, |
|
isServer: false |
|
}) |
|
client.start(version) |
|
done() |
|
}) |
|
}) |
|
}) |
|
|
|
afterEach(function (done) { |
|
client.socket.destroy() |
|
server.close(done) |
|
}) |
|
|
|
it('should process GET request', function (done) { |
|
var stream = client.request({ |
|
method: 'GET', |
|
path: '/get', |
|
headers: { |
|
a: 'b' |
|
} |
|
}, function (err) { |
|
assert(!err) |
|
|
|
stream.on('error', (err) => { |
|
done(err) |
|
}) |
|
|
|
stream.on('response', function (status, headers) { |
|
assert.strictEqual(status, 200) |
|
assert.strictEqual(headers.ok, 'yes') |
|
|
|
fixtures.expectData(stream, 'response', done) |
|
}) |
|
|
|
stream.end() |
|
}) |
|
|
|
server.on('request', function (req, res) { |
|
assert.strictEqual(req.isSpdy, res.isSpdy) |
|
assert.strictEqual(req.spdyVersion, res.spdyVersion) |
|
assert(req.isSpdy) |
|
if (!plain) { |
|
assert(req.socket.encrypted) |
|
assert(req.socket.getPeerCertificate()) |
|
} |
|
|
|
// Auto-detection |
|
if (version === 3.1) { |
|
assert(req.spdyVersion >= 3 && req.spdyVersion <= 3.1) |
|
} else { |
|
assert.strictEqual(req.spdyVersion, version) |
|
} |
|
assert(req.spdyStream) |
|
assert(res.spdyStream) |
|
|
|
assert.strictEqual(req.method, 'GET') |
|
assert.strictEqual(req.url, '/get') |
|
assert.deepStrictEqual(req.headers, { a: 'b', host: 'localhost' }) |
|
|
|
req.on('end', function () { |
|
res.writeHead(200, { |
|
ok: 'yes' |
|
}) |
|
res.end('response') |
|
assert(res.finished, 'res.finished should be set') |
|
}) |
|
req.resume() |
|
}) |
|
}) |
|
|
|
it('should process POST request', function (done) { |
|
var stream = client.request({ |
|
method: 'POST', |
|
path: '/post' |
|
}, function (err) { |
|
assert(!err) |
|
|
|
stream.on('response', function (status, headers) { |
|
assert.strictEqual(status, 200) |
|
assert.strictEqual(headers.ok, 'yes') |
|
|
|
fixtures.expectData(stream, 'response', next) |
|
}) |
|
|
|
stream.end('request') |
|
}) |
|
|
|
server.on('request', function (req, res) { |
|
assert.strictEqual(req.method, 'POST') |
|
assert.strictEqual(req.url, '/post') |
|
|
|
res.writeHead(200, { |
|
ok: 'yes' |
|
}) |
|
res.end('response') |
|
|
|
fixtures.expectData(req, 'request', next) |
|
}) |
|
|
|
var waiting = 2 |
|
function next () { |
|
if (--waiting === 0) { |
|
return done() |
|
} |
|
} |
|
}) |
|
|
|
it('should process expect-continue request', function (done) { |
|
var stream = client.request({ |
|
method: 'GET', |
|
path: '/get', |
|
headers: { |
|
Expect: '100-continue' |
|
} |
|
}, function (err) { |
|
assert(!err) |
|
|
|
stream.on('response', function (status, headers) { |
|
assert.strictEqual(status, 100) |
|
|
|
fixtures.expectData(stream, 'response', done) |
|
}) |
|
|
|
stream.end() |
|
}) |
|
|
|
server.on('request', function (req, res) { |
|
req.on('end', function () { |
|
res.end('response') |
|
}) |
|
req.resume() |
|
}) |
|
}) |
|
|
|
it('should emit `checkContinue` request', function (done) { |
|
var stream = client.request({ |
|
method: 'GET', |
|
path: '/get', |
|
headers: { |
|
Expect: '100-continue' |
|
} |
|
}, function (err) { |
|
assert(!err) |
|
|
|
stream.on('response', function (status, headers) { |
|
assert.strictEqual(status, 100) |
|
|
|
fixtures.expectData(stream, 'response', done) |
|
}) |
|
|
|
stream.end() |
|
}) |
|
|
|
server.on('checkContinue', function (req, res) { |
|
req.on('end', function () { |
|
res.writeContinue() |
|
res.end('response') |
|
}) |
|
req.resume() |
|
}) |
|
}) |
|
|
|
it('should send PUSH_PROMISE', function (done) { |
|
var stream = client.request({ |
|
method: 'POST', |
|
path: '/page' |
|
}, function (err) { |
|
assert(!err) |
|
|
|
stream.on('pushPromise', function (push) { |
|
assert.strictEqual(push.path, '/push') |
|
assert.strictEqual(push.headers.yes, 'push') |
|
|
|
fixtures.expectData(push, 'push', next) |
|
fixtures.expectData(stream, 'response', next) |
|
}) |
|
|
|
stream.end('request') |
|
}) |
|
|
|
server.on('request', function (req, res) { |
|
assert.strictEqual(req.method, 'POST') |
|
assert.strictEqual(req.url, '/page') |
|
|
|
res.writeHead(200, { |
|
ok: 'yes' |
|
}) |
|
|
|
var push = res.push('/push', { |
|
request: { |
|
yes: 'push' |
|
} |
|
}) |
|
push.end('push') |
|
|
|
res.end('response') |
|
|
|
fixtures.expectData(req, 'request', next) |
|
}) |
|
|
|
var waiting = 3 |
|
function next () { |
|
if (--waiting === 0) { |
|
return done() |
|
} |
|
} |
|
}) |
|
|
|
it('should receive trailing headers', function (done) { |
|
var stream = client.request({ |
|
method: 'POST', |
|
path: '/post' |
|
}, function (err) { |
|
assert(!err) |
|
|
|
stream.sendHeaders({ trai: 'ler' }) |
|
stream.end() |
|
|
|
stream.on('response', function (status, headers) { |
|
assert.strictEqual(status, 200) |
|
assert.strictEqual(headers.ok, 'yes') |
|
|
|
fixtures.expectData(stream, 'response', done) |
|
}) |
|
}) |
|
|
|
server.on('request', function (req, res) { |
|
var gotHeaders = false |
|
req.on('trailers', function (headers) { |
|
gotHeaders = true |
|
assert.strictEqual(headers.trai, 'ler') |
|
}) |
|
|
|
req.on('end', function () { |
|
assert(gotHeaders) |
|
|
|
res.writeHead(200, { |
|
ok: 'yes' |
|
}) |
|
res.end('response') |
|
}) |
|
req.resume() |
|
}) |
|
}) |
|
|
|
it('should call .writeHead() automatically', function (done) { |
|
var stream = client.request({ |
|
method: 'POST', |
|
path: '/post' |
|
}, function (err) { |
|
assert(!err) |
|
|
|
stream.on('response', function (status, headers) { |
|
assert.strictEqual(status, 300) |
|
|
|
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() |
|
}) |
|
}) |
|
|
|
it('should not crash on .writeHead() after socket close', function (done) { |
|
var stream = client.request({ |
|
method: 'POST', |
|
path: '/post' |
|
}, function (err) { |
|
assert(!err) |
|
|
|
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() |
|
}) |
|
}) |
|
}) |
|
|
|
it('should not crash on .push() after socket close', function (done) { |
|
var stream = client.request({ |
|
method: 'POST', |
|
path: '/post' |
|
}, function (err) { |
|
assert(!err) |
|
|
|
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.strictEqual(res.push('/push', {}), undefined) |
|
res.end('response') |
|
}) |
|
done() |
|
}) |
|
}) |
|
}) |
|
|
|
it('should end response after writing everything down', function (done) { |
|
var stream = client.request({ |
|
method: 'GET', |
|
path: '/post' |
|
}, function (err) { |
|
assert(!err) |
|
|
|
stream.on('response', function (status, headers) { |
|
assert.strictEqual(status, 200) |
|
|
|
fixtures.expectData(stream, 'hello world, what\'s up?', done) |
|
}) |
|
|
|
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() |
|
}) |
|
}) |
|
|
|
it('should handle x-forwarded-for', function (done) { |
|
client.sendXForwardedFor('1.2.3.4') |
|
|
|
var stream = client.request({ |
|
method: 'GET', |
|
path: '/post' |
|
}, function (err) { |
|
assert(!err) |
|
|
|
stream.resume() |
|
stream.on('end', done) |
|
stream.end() |
|
}) |
|
|
|
server.on('request', function (req, res) { |
|
assert.strictEqual(req.headers['x-forwarded-for'], '1.2.3.4') |
|
req.resume() |
|
res.end() |
|
}) |
|
}) |
|
|
|
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 () {}) |
|
|
|
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.strictEqual(req.isSpdy, res.isSpdy) |
|
assert.strictEqual(req.spdyVersion, res.spdyVersion) |
|
assert(!req.isSpdy) |
|
assert.strictEqual(req.spdyVersion, 1) |
|
|
|
res.writeHead(200) |
|
res.end() |
|
}) |
|
|
|
server.listen(fixtures.port, function () { |
|
var req = https.request({ |
|
agent: false, |
|
rejectUnauthorized: false, |
|
NPNProtocols: ['http/1.1'], |
|
port: fixtures.port, |
|
method: 'GET', |
|
path: '/' |
|
}, function (res) { |
|
assert.strictEqual(res.statusCode, 200) |
|
res.resume() |
|
res.on('end', function () { |
|
server.close(done) |
|
}) |
|
}) |
|
|
|
req.end() |
|
}) |
|
}) |
|
|
|
it('should support custom base', function (done) { |
|
function Pseuver (options, listener) { |
|
https.Server.call(this, options, listener) |
|
} |
|
util.inherits(Pseuver, https.Server) |
|
|
|
var server = spdy.createServer(Pseuver, fixtures.keys, function (req, res) { |
|
assert.strictEqual(req.isSpdy, res.isSpdy) |
|
assert.strictEqual(req.spdyVersion, res.spdyVersion) |
|
assert(!req.isSpdy) |
|
assert.strictEqual(req.spdyVersion, 1) |
|
|
|
res.writeHead(200) |
|
res.end() |
|
}) |
|
|
|
server.listen(fixtures.port, function () { |
|
var req = https.request({ |
|
agent: false, |
|
rejectUnauthorized: false, |
|
NPNProtocols: ['http/1.1'], |
|
port: fixtures.port, |
|
method: 'GET', |
|
path: '/' |
|
}, function (res) { |
|
assert.strictEqual(res.statusCode, 200) |
|
res.resume() |
|
res.on('end', function () { |
|
server.close(done) |
|
}) |
|
}) |
|
|
|
req.end() |
|
}) |
|
}) |
|
})
|
|
|