import * as http from 'http'; import { parse } from 'url'; import * as zlib from 'zlib'; import * as stream from 'stream'; import { multipart as Multipart } from 'parted'; let convert; try { convert = require('encoding').convert; } catch(e) {} export default class TestServer { constructor() { this.server = http.createServer(this.router); this.port = 30001; this.hostname = 'localhost'; // node 8 default keepalive timeout is 5000ms // make it shorter here as we want to close server quickly at the end of tests this.server.keepAliveTimeout = 1000; this.server.on('error', function(err) { console.log(err.stack); }); this.server.on('connection', function(socket) { socket.setTimeout(1500); }); } start(cb) { this.server.listen(this.port, this.hostname, cb); } stop(cb) { this.server.close(cb); } router(req, res) { let p = parse(req.url).pathname; if (p === '/hello') { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('world'); } if (p === '/plain') { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('text'); } if (p === '/options') { res.statusCode = 200; res.setHeader('Allow', 'GET, HEAD, OPTIONS'); res.end('hello world'); } if (p === '/html') { res.statusCode = 200; res.setHeader('Content-Type', 'text/html'); res.end(''); } if (p === '/json') { res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ name: 'value' })); } if (p === '/gzip') { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.setHeader('Content-Encoding', 'gzip'); zlib.gzip('hello world', function(err, buffer) { res.end(buffer); }); } if (p === '/gzip-truncated') { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.setHeader('Content-Encoding', 'gzip'); zlib.gzip('hello world', function(err, buffer) { // truncate the CRC checksum and size check at the end of the stream res.end(buffer.slice(0, buffer.length - 8)); }); } if (p === '/deflate') { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.setHeader('Content-Encoding', 'deflate'); zlib.deflate('hello world', function(err, buffer) { res.end(buffer); }); } if (p === '/deflate-raw') { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.setHeader('Content-Encoding', 'deflate'); zlib.deflateRaw('hello world', function(err, buffer) { res.end(buffer); }); } if (p === '/sdch') { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.setHeader('Content-Encoding', 'sdch'); res.end('fake sdch string'); } if (p === '/invalid-content-encoding') { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.setHeader('Content-Encoding', 'gzip'); res.end('fake gzip string'); } if (p === '/invalid-header') { res.setHeader('Content-Type', 'text/plain'); res.writeHead(200); // HACK: add a few invalid headers to the generated header string before // it is actually sent to the socket. res._header = res._header.replace(/\r\n$/, [ 'Invalid-Header : abc\r\n', 'Invalid-Header-Value: \x07k\r\n', 'Set-Cookie: \x07k\r\n', 'Set-Cookie: \x07kk\r\n', ].join('') + '\r\n'); res.end('hello world\n'); } if (p === '/timeout') { setTimeout(function() { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('text'); }, 1000); } if (p === '/slow') { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.write('test'); setTimeout(function() { res.end('test'); }, 1000); } if (p === '/cookie') { res.statusCode = 200; res.setHeader('Set-Cookie', ['a=1', 'b=1']); res.end('cookie'); } if (p === '/size/chunk') { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); setTimeout(function() { res.write('test'); }, 50); setTimeout(function() { res.end('test'); }, 100); } if (p === '/size/long') { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('testtest'); } if (p === '/encoding/gbk') { res.statusCode = 200; res.setHeader('Content-Type', 'text/html'); res.end(convert('