• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const http = require('http');
4
5const fixed = 'C'.repeat(20 * 1024);
6const storedBytes = Object.create(null);
7const storedBuffer = Object.create(null);
8const storedUnicode = Object.create(null);
9
10const useDomains = process.env.NODE_USE_DOMAINS;
11
12// Set up one global domain.
13let domain;
14if (useDomains) {
15  domain = require('domain');
16  const gdom = domain.create();
17  gdom.on('error', (er) => {
18    console.error('Error on global domain', er);
19    throw er;
20  });
21  gdom.enter();
22}
23
24module.exports = http.createServer((req, res) => {
25  if (useDomains) {
26    const dom = domain.create();
27    dom.add(req);
28    dom.add(res);
29  }
30
31  // URL format: /<type>/<length>/<chunks>/<responseBehavior>/chunkedEnc
32  const params = req.url.split('/');
33  const command = params[1];
34  let body = '';
35  const arg = params[2];
36  const n_chunks = parseInt(params[3], 10);
37  const resHow = params.length >= 5 ? params[4] : 'normal';
38  const chunkedEnc = params.length >= 6 && params[5] === '0' ? false : true;
39  let status = 200;
40
41  let n, i;
42  if (command === 'bytes') {
43    n = ~~arg;
44    if (n <= 0)
45      throw new Error('bytes called with n <= 0');
46    if (storedBytes[n] === undefined) {
47      storedBytes[n] = 'C'.repeat(n);
48    }
49    body = storedBytes[n];
50  } else if (command === 'buffer') {
51    n = ~~arg;
52    if (n <= 0)
53      throw new Error('buffer called with n <= 0');
54    if (storedBuffer[n] === undefined) {
55      storedBuffer[n] = Buffer.allocUnsafe(n);
56      for (i = 0; i < n; i++) {
57        storedBuffer[n][i] = 'C'.charCodeAt(0);
58      }
59    }
60    body = storedBuffer[n];
61  } else if (command === 'unicode') {
62    n = ~~arg;
63    if (n <= 0)
64      throw new Error('unicode called with n <= 0');
65    if (storedUnicode[n] === undefined) {
66      storedUnicode[n] = '\u263A'.repeat(n);
67    }
68    body = storedUnicode[n];
69  } else if (command === 'quit') {
70    res.connection.server.close();
71    body = 'quitting';
72  } else if (command === 'fixed') {
73    body = fixed;
74  } else if (command === 'echo') {
75    switch (resHow) {
76      case 'setHeader':
77        res.statusCode = 200;
78        res.setHeader('Content-Type', 'text/plain');
79        res.setHeader('Transfer-Encoding', 'chunked');
80        break;
81      case 'setHeaderWH':
82        res.setHeader('Content-Type', 'text/plain');
83        res.writeHead(200, { 'Transfer-Encoding': 'chunked' });
84        break;
85      default:
86        res.writeHead(200, {
87          'Content-Type': 'text/plain',
88          'Transfer-Encoding': 'chunked'
89        });
90    }
91    req.pipe(res);
92    return;
93  } else {
94    status = 404;
95    body = 'not found\n';
96  }
97
98  // example: http://localhost:port/bytes/512/4
99  // sends a 512 byte body in 4 chunks of 128 bytes
100  const len = body.length;
101  switch (resHow) {
102    case 'setHeader':
103      res.statusCode = status;
104      res.setHeader('Content-Type', 'text/plain');
105      if (chunkedEnc)
106        res.setHeader('Transfer-Encoding', 'chunked');
107      else
108        res.setHeader('Content-Length', len.toString());
109      break;
110    case 'setHeaderWH':
111      res.setHeader('Content-Type', 'text/plain');
112      if (chunkedEnc)
113        res.writeHead(status, { 'Transfer-Encoding': 'chunked' });
114      else
115        res.writeHead(status, { 'Content-Length': len.toString() });
116      break;
117    default:
118      if (chunkedEnc) {
119        res.writeHead(status, {
120          'Content-Type': 'text/plain',
121          'Transfer-Encoding': 'chunked'
122        });
123      } else {
124        res.writeHead(status, {
125          'Content-Type': 'text/plain',
126          'Content-Length': len.toString()
127        });
128      }
129  }
130  // send body in chunks
131  if (n_chunks > 1) {
132    const step = Math.floor(len / n_chunks) || 1;
133    for (i = 0, n = (n_chunks - 1); i < n; ++i)
134      res.write(body.slice(i * step, i * step + step));
135    res.end(body.slice((n_chunks - 1) * step));
136  } else {
137    res.end(body);
138  }
139});
140