michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0:
michael@0: var http2 = require('../node-http2');
michael@0: var fs = require('fs');
michael@0: var url = require('url');
michael@0: var crypto = require('crypto');
michael@0:
michael@0: // Hook into the decompression code to log the decompressed name-value pairs
michael@0: var http2_compression = require('../node-http2/node_modules/http2-protocol/lib/compressor');
michael@0: var HeaderSetDecompressor = http2_compression.HeaderSetDecompressor;
michael@0: var originalRead = HeaderSetDecompressor.prototype.read;
michael@0: var lastDecompressor;
michael@0: var decompressedPairs;
michael@0: HeaderSetDecompressor.prototype.read = function() {
michael@0: if (this != lastDecompressor) {
michael@0: lastDecompressor = this;
michael@0: decompressedPairs = [];
michael@0: }
michael@0: var pair = originalRead.apply(this, arguments);
michael@0: if (pair) {
michael@0: decompressedPairs.push(pair);
michael@0: }
michael@0: return pair;
michael@0: }
michael@0:
michael@0: function getHttpContent(path) {
michael@0: var content = '' +
michael@0: '' +
michael@0: '
HOORAY!' +
michael@0: 'You Win! (by requesting' + path + ')' +
michael@0: '';
michael@0: return content;
michael@0: }
michael@0:
michael@0: function generateContent(size) {
michael@0: var content = '';
michael@0: for (var i = 0; i < size; i++) {
michael@0: content += '0';
michael@0: }
michael@0: return content;
michael@0: }
michael@0:
michael@0: /* This takes care of responding to the multiplexed request for us */
michael@0: var m = {
michael@0: mp1res: null,
michael@0: mp2res: null,
michael@0: buf: null,
michael@0: mp1start: 0,
michael@0: mp2start: 0,
michael@0:
michael@0: checkReady: function() {
michael@0: if (this.mp1res != null && this.mp2res != null) {
michael@0: this.buf = generateContent(30*1024);
michael@0: this.mp1start = 0;
michael@0: this.mp2start = 0;
michael@0: this.send(this.mp1res, 0);
michael@0: setTimeout(this.send.bind(this, this.mp2res, 0), 5);
michael@0: }
michael@0: },
michael@0:
michael@0: send: function(res, start) {
michael@0: var end = Math.min(start + 1024, this.buf.length);
michael@0: var content = this.buf.substring(start, end);
michael@0: res.write(content);
michael@0: if (end < this.buf.length) {
michael@0: setTimeout(this.send.bind(this, res, end), 10);
michael@0: } else {
michael@0: res.end();
michael@0: }
michael@0: }
michael@0: };
michael@0:
michael@0: function handleRequest(req, res) {
michael@0: var u = url.parse(req.url);
michael@0: var content = getHttpContent(u.pathname);
michael@0: var push;
michael@0:
michael@0: if (req.httpVersionMajor === 2) {
michael@0: res.setHeader('X-Connection-Http2', 'yes');
michael@0: res.setHeader('X-Http2-StreamId', '' + req.stream.id);
michael@0: } else {
michael@0: res.setHeader('X-Connection-Http2', 'no');
michael@0: }
michael@0:
michael@0: if (u.pathname === '/exit') {
michael@0: res.setHeader('Content-Type', 'text/plain');
michael@0: res.writeHead(200);
michael@0: res.end('ok');
michael@0: process.exit();
michael@0: }
michael@0:
michael@0: else if ((u.pathname === '/multiplex1') && (req.httpVersionMajor === 2)) {
michael@0: res.setHeader('Content-Type', 'text/plain');
michael@0: res.writeHead(200);
michael@0: m.mp1res = res;
michael@0: m.checkReady();
michael@0: return;
michael@0: }
michael@0:
michael@0: else if ((u.pathname === '/multiplex2') && (req.httpVersionMajor === 2)) {
michael@0: res.setHeader('Content-Type', 'text/plain');
michael@0: res.writeHead(200);
michael@0: m.mp2res = res;
michael@0: m.checkReady();
michael@0: return;
michael@0: }
michael@0:
michael@0: else if (u.pathname === "/header") {
michael@0: var val = req.headers["x-test-header"];
michael@0: if (val) {
michael@0: res.setHeader("X-Received-Test-Header", val);
michael@0: }
michael@0: }
michael@0:
michael@0: else if (u.pathname === "/cookie_crumbling") {
michael@0: res.setHeader("X-Received-Header-Pairs", JSON.stringify(decompressedPairs));
michael@0: }
michael@0:
michael@0: else if (u.pathname === "/push") {
michael@0: push = res.push('/push.js');
michael@0: push.writeHead(200, {
michael@0: 'content-type': 'application/javascript',
michael@0: 'pushed' : 'yes',
michael@0: 'content-length' : 11,
michael@0: 'X-Connection-Http2': 'yes'
michael@0: });
michael@0: push.end('// comments');
michael@0: content = ' body text';
michael@0: }
michael@0:
michael@0: else if (u.pathname === "/push2") {
michael@0: push = res.push('/push2.js');
michael@0: push.writeHead(200, {
michael@0: 'content-type': 'application/javascript',
michael@0: 'pushed' : 'yes',
michael@0: // no content-length
michael@0: 'X-Connection-Http2': 'yes'
michael@0: });
michael@0: push.end('// comments');
michael@0: content = ' body text';
michael@0: }
michael@0:
michael@0: else if (u.pathname === "/big") {
michael@0: content = generateContent(128 * 1024);
michael@0: var hash = crypto.createHash('md5');
michael@0: hash.update(content);
michael@0: var md5 = hash.digest('hex');
michael@0: res.setHeader("X-Expected-MD5", md5);
michael@0: }
michael@0:
michael@0: else if (u.pathname === "/post") {
michael@0: if (req.method != "POST") {
michael@0: res.writeHead(405);
michael@0: res.end('Unexpected method: ' + req.method);
michael@0: return;
michael@0: }
michael@0:
michael@0: var post_hash = crypto.createHash('md5');
michael@0: req.on('data', function receivePostData(chunk) {
michael@0: post_hash.update(chunk.toString());
michael@0: });
michael@0: req.on('end', function finishPost() {
michael@0: var md5 = post_hash.digest('hex');
michael@0: res.setHeader('X-Calculated-MD5', md5);
michael@0: res.writeHead(200);
michael@0: res.end(content);
michael@0: });
michael@0:
michael@0: return;
michael@0: }
michael@0:
michael@0: res.setHeader('Content-Type', 'text/html');
michael@0: res.writeHead(200);
michael@0: res.end(content);
michael@0: }
michael@0:
michael@0: // Set up the SSL certs for our server
michael@0: var options = {
michael@0: key: fs.readFileSync(__dirname + '/../moz-spdy/spdy-key.pem'),
michael@0: cert: fs.readFileSync(__dirname + '/../moz-spdy/spdy-cert.pem'),
michael@0: ca: fs.readFileSync(__dirname + '/../moz-spdy/spdy-ca.pem'),
michael@0: //, log: require('../node-http2/test/util').createLogger('server')
michael@0: };
michael@0:
michael@0: var server = http2.createServer(options, handleRequest);
michael@0: server.on('connection', function(socket) {
michael@0: socket.on('error', function() {
michael@0: // Ignoring SSL socket errors, since they usually represent a connection that was tore down
michael@0: // by the browser because of an untrusted certificate. And this happens at least once, when
michael@0: // the first test case if done.
michael@0: });
michael@0: });
michael@0: server.listen(6944);
michael@0: console.log('HTTP2 server listening on port 6944');