server.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. var http = require('http');
  2. var parse = require('url').parse;
  3. var zlib = require('zlib');
  4. var stream = require('stream');
  5. var convert = require('encoding').convert;
  6. var Multipart = require('parted').multipart;
  7. module.exports = TestServer;
  8. function TestServer() {
  9. this.server = http.createServer(this.router);
  10. this.port = 30001;
  11. this.hostname = 'localhost';
  12. // node 8 default keepalive timeout is 5000ms
  13. // make it shorter here as we want to close server quickly at the end of tests
  14. this.server.keepAliveTimeout = 1000;
  15. this.server.on('error', function(err) {
  16. console.log(err.stack);
  17. });
  18. this.server.on('connection', function(socket) {
  19. socket.setTimeout(1500);
  20. });
  21. }
  22. TestServer.prototype.start = function(cb) {
  23. this.server.listen(this.port, this.hostname, cb);
  24. }
  25. TestServer.prototype.stop = function(cb) {
  26. this.server.close(cb);
  27. }
  28. TestServer.prototype.router = function(req, res) {
  29. var p = parse(req.url).pathname;
  30. if (p === '/hello') {
  31. res.statusCode = 200;
  32. res.setHeader('Content-Type', 'text/plain');
  33. res.end('world');
  34. }
  35. if (p === '/plain') {
  36. res.statusCode = 200;
  37. res.setHeader('Content-Type', 'text/plain');
  38. res.end('text');
  39. }
  40. if (p === '/options') {
  41. res.statusCode = 200;
  42. res.setHeader('Allow', 'GET, HEAD, OPTIONS');
  43. res.end('hello world');
  44. }
  45. if (p === '/html') {
  46. res.statusCode = 200;
  47. res.setHeader('Content-Type', 'text/html');
  48. res.end('<html></html>');
  49. }
  50. if (p === '/json') {
  51. res.statusCode = 200;
  52. res.setHeader('Content-Type', 'application/json');
  53. res.end(JSON.stringify({
  54. name: 'value'
  55. }));
  56. }
  57. if (p === '/gzip') {
  58. res.statusCode = 200;
  59. res.setHeader('Content-Type', 'text/plain');
  60. res.setHeader('Content-Encoding', 'gzip');
  61. zlib.gzip('hello world', function(err, buffer) {
  62. res.end(buffer);
  63. });
  64. }
  65. if (p === '/deflate') {
  66. res.statusCode = 200;
  67. res.setHeader('Content-Type', 'text/plain');
  68. res.setHeader('Content-Encoding', 'deflate');
  69. zlib.deflate('hello world', function(err, buffer) {
  70. res.end(buffer);
  71. });
  72. }
  73. if (p === '/deflate-raw') {
  74. res.statusCode = 200;
  75. res.setHeader('Content-Type', 'text/plain');
  76. res.setHeader('Content-Encoding', 'deflate');
  77. zlib.deflateRaw('hello world', function(err, buffer) {
  78. res.end(buffer);
  79. });
  80. }
  81. if (p === '/sdch') {
  82. res.statusCode = 200;
  83. res.setHeader('Content-Type', 'text/plain');
  84. res.setHeader('Content-Encoding', 'sdch');
  85. res.end('fake sdch string');
  86. }
  87. if (p === '/invalid-content-encoding') {
  88. res.statusCode = 200;
  89. res.setHeader('Content-Type', 'text/plain');
  90. res.setHeader('Content-Encoding', 'gzip');
  91. res.end('fake gzip string');
  92. }
  93. if (p === '/timeout') {
  94. setTimeout(function() {
  95. res.statusCode = 200;
  96. res.setHeader('Content-Type', 'text/plain');
  97. res.end('text');
  98. }, 1000);
  99. }
  100. if (p === '/slow') {
  101. res.statusCode = 200;
  102. res.setHeader('Content-Type', 'text/plain');
  103. res.write('test');
  104. setTimeout(function() {
  105. res.end('test');
  106. }, 1000);
  107. }
  108. if (p === '/cookie') {
  109. res.statusCode = 200;
  110. res.setHeader('Set-Cookie', ['a=1', 'b=1']);
  111. res.end('cookie');
  112. }
  113. if (p === '/size/chunk') {
  114. res.statusCode = 200;
  115. res.setHeader('Content-Type', 'text/plain');
  116. setTimeout(function() {
  117. res.write('test');
  118. }, 50);
  119. setTimeout(function() {
  120. res.end('test');
  121. }, 100);
  122. }
  123. if (p === '/size/long') {
  124. res.statusCode = 200;
  125. res.setHeader('Content-Type', 'text/plain');
  126. res.end('testtest');
  127. }
  128. if (p === '/encoding/gbk') {
  129. res.statusCode = 200;
  130. res.setHeader('Content-Type', 'text/html');
  131. res.end(convert('<meta charset="gbk"><div>中文</div>', 'gbk'));
  132. }
  133. if (p === '/encoding/gb2312') {
  134. res.statusCode = 200;
  135. res.setHeader('Content-Type', 'text/html');
  136. res.end(convert('<meta http-equiv="Content-Type" content="text/html; charset=gb2312"><div>中文</div>', 'gb2312'));
  137. }
  138. if (p === '/encoding/shift-jis') {
  139. res.statusCode = 200;
  140. res.setHeader('Content-Type', 'text/html; charset=Shift-JIS');
  141. res.end(convert('<div>日本語</div>', 'Shift_JIS'));
  142. }
  143. if (p === '/encoding/euc-jp') {
  144. res.statusCode = 200;
  145. res.setHeader('Content-Type', 'text/xml');
  146. res.end(convert('<?xml version="1.0" encoding="EUC-JP"?><title>日本語</title>', 'EUC-JP'));
  147. }
  148. if (p === '/encoding/utf8') {
  149. res.statusCode = 200;
  150. res.end('中文');
  151. }
  152. if (p === '/encoding/order1') {
  153. res.statusCode = 200;
  154. res.setHeader('Content-Type', 'charset=gbk; text/plain');
  155. res.end(convert('中文', 'gbk'));
  156. }
  157. if (p === '/encoding/order2') {
  158. res.statusCode = 200;
  159. res.setHeader('Content-Type', 'text/plain; charset=gbk; qs=1');
  160. res.end(convert('中文', 'gbk'));
  161. }
  162. if (p === '/encoding/chunked') {
  163. res.statusCode = 200;
  164. res.setHeader('Content-Type', 'text/html');
  165. res.setHeader('Transfer-Encoding', 'chunked');
  166. var padding = 'a';
  167. for (var i = 0; i < 10; i++) {
  168. res.write(padding);
  169. }
  170. res.end(convert('<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" /><div>日本語</div>', 'Shift_JIS'));
  171. }
  172. if (p === '/encoding/invalid') {
  173. res.statusCode = 200;
  174. res.setHeader('Content-Type', 'text/html');
  175. res.setHeader('Transfer-Encoding', 'chunked');
  176. // because node v0.12 doesn't have str.repeat
  177. var padding = new Array(120 + 1).join('a');
  178. for (var i = 0; i < 10; i++) {
  179. res.write(padding);
  180. }
  181. res.end(convert('中文', 'gbk'));
  182. }
  183. if (p === '/redirect/301') {
  184. res.statusCode = 301;
  185. res.setHeader('Location', '/inspect');
  186. res.end();
  187. }
  188. if (p === '/redirect/302') {
  189. res.statusCode = 302;
  190. res.setHeader('Location', '/inspect');
  191. res.end();
  192. }
  193. if (p === '/redirect/303') {
  194. res.statusCode = 303;
  195. res.setHeader('Location', '/inspect');
  196. res.end();
  197. }
  198. if (p === '/redirect/307') {
  199. res.statusCode = 307;
  200. res.setHeader('Location', '/inspect');
  201. res.end();
  202. }
  203. if (p === '/redirect/308') {
  204. res.statusCode = 308;
  205. res.setHeader('Location', '/inspect');
  206. res.end();
  207. }
  208. if (p === '/redirect/chain') {
  209. res.statusCode = 301;
  210. res.setHeader('Location', '/redirect/301');
  211. res.end();
  212. }
  213. if (p === '/error/redirect') {
  214. res.statusCode = 301;
  215. //res.setHeader('Location', '/inspect');
  216. res.end();
  217. }
  218. if (p === '/error/400') {
  219. res.statusCode = 400;
  220. res.setHeader('Content-Type', 'text/plain');
  221. res.end('client error');
  222. }
  223. if (p === '/error/404') {
  224. res.statusCode = 404;
  225. res.setHeader('Content-Encoding', 'gzip');
  226. res.end();
  227. }
  228. if (p === '/error/500') {
  229. res.statusCode = 500;
  230. res.setHeader('Content-Type', 'text/plain');
  231. res.end('server error');
  232. }
  233. if (p === '/error/reset') {
  234. res.destroy();
  235. }
  236. if (p === '/error/json') {
  237. res.statusCode = 200;
  238. res.setHeader('Content-Type', 'application/json');
  239. res.end('invalid json');
  240. }
  241. if (p === '/no-content') {
  242. res.statusCode = 204;
  243. res.end();
  244. }
  245. if (p === '/no-content/gzip') {
  246. res.statusCode = 204;
  247. res.setHeader('Content-Encoding', 'gzip');
  248. res.end();
  249. }
  250. if (p === '/not-modified') {
  251. res.statusCode = 304;
  252. res.end();
  253. }
  254. if (p === '/not-modified/gzip') {
  255. res.statusCode = 304;
  256. res.setHeader('Content-Encoding', 'gzip');
  257. res.end();
  258. }
  259. if (p === '/inspect') {
  260. res.statusCode = 200;
  261. res.setHeader('Content-Type', 'application/json');
  262. var body = '';
  263. req.on('data', function(c) { body += c });
  264. req.on('end', function() {
  265. res.end(JSON.stringify({
  266. method: req.method,
  267. url: req.url,
  268. headers: req.headers,
  269. body: body
  270. }));
  271. });
  272. }
  273. if (p === '/multipart') {
  274. res.statusCode = 200;
  275. res.setHeader('Content-Type', 'application/json');
  276. var parser = new Multipart(req.headers['content-type']);
  277. var body = '';
  278. parser.on('part', function(field, part) {
  279. body += field + '=' + part;
  280. });
  281. parser.on('end', function() {
  282. res.end(JSON.stringify({
  283. method: req.method,
  284. url: req.url,
  285. headers: req.headers,
  286. body: body
  287. }));
  288. });
  289. req.pipe(parser);
  290. }
  291. }