11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_cirequire('../common');
41cb0ef41Sopenharmony_ciconst http = require('http');
51cb0ef41Sopenharmony_ciconst net = require('net');
61cb0ef41Sopenharmony_ciconst url = require('url');
71cb0ef41Sopenharmony_ciconst assert = require('assert');
81cb0ef41Sopenharmony_ciconst Countdown = require('../common/countdown');
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci// Response splitting example, credit: Amit Klein, Safebreach
111cb0ef41Sopenharmony_ciconst str = '/welcome?lang=bar%c4%8d%c4%8aContent­Length:%200%c4%8d%c4%8a%c' +
121cb0ef41Sopenharmony_ci            '4%8d%c4%8aHTTP/1.1%20200%20OK%c4%8d%c4%8aContent­Length:%202' +
131cb0ef41Sopenharmony_ci            '0%c4%8d%c4%8aLast­Modified:%20Mon,%2027%20Oct%202003%2014:50:18' +
141cb0ef41Sopenharmony_ci            '%20GMT%c4%8d%c4%8aContent­Type:%20text/html%c4%8d%c4%8a%c4%8' +
151cb0ef41Sopenharmony_ci            'd%c4%8a%3chtml%3eGotcha!%3c/html%3e';
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci// Response splitting example, credit: Сковорода Никита Андреевич (@ChALkeR)
181cb0ef41Sopenharmony_ciconst x = 'fooഊSet-Cookie: foo=barഊഊ<script>alert("Hi!")</script>';
191cb0ef41Sopenharmony_ciconst y = 'foo⠊Set-Cookie: foo=bar';
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_cilet count = 0;
221cb0ef41Sopenharmony_ciconst countdown = new Countdown(3, () => server.close());
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_cifunction test(res, code, key, value) {
251cb0ef41Sopenharmony_ci  const header = { [key]: value };
261cb0ef41Sopenharmony_ci  assert.throws(
271cb0ef41Sopenharmony_ci    () => res.writeHead(code, header),
281cb0ef41Sopenharmony_ci    {
291cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_CHAR',
301cb0ef41Sopenharmony_ci      name: 'TypeError',
311cb0ef41Sopenharmony_ci      message: `Invalid character in header content ["${key}"]`
321cb0ef41Sopenharmony_ci    }
331cb0ef41Sopenharmony_ci  );
341cb0ef41Sopenharmony_ci}
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ciconst server = http.createServer((req, res) => {
371cb0ef41Sopenharmony_ci  switch (count++) {
381cb0ef41Sopenharmony_ci    case 0: {
391cb0ef41Sopenharmony_ci      const loc = url.parse(req.url, true).query.lang;
401cb0ef41Sopenharmony_ci      test(res, 302, 'Location', `/foo?lang=${loc}`);
411cb0ef41Sopenharmony_ci      break;
421cb0ef41Sopenharmony_ci    }
431cb0ef41Sopenharmony_ci    case 1:
441cb0ef41Sopenharmony_ci      test(res, 200, 'foo', x);
451cb0ef41Sopenharmony_ci      break;
461cb0ef41Sopenharmony_ci    case 2:
471cb0ef41Sopenharmony_ci      test(res, 200, 'foo', y);
481cb0ef41Sopenharmony_ci      break;
491cb0ef41Sopenharmony_ci    default:
501cb0ef41Sopenharmony_ci      assert.fail('should not get to here.');
511cb0ef41Sopenharmony_ci  }
521cb0ef41Sopenharmony_ci  countdown.dec();
531cb0ef41Sopenharmony_ci  res.end('ok');
541cb0ef41Sopenharmony_ci});
551cb0ef41Sopenharmony_ciserver.listen(0, () => {
561cb0ef41Sopenharmony_ci  const end = 'HTTP/1.1\r\n\r\n';
571cb0ef41Sopenharmony_ci  const client = net.connect({ port: server.address().port }, () => {
581cb0ef41Sopenharmony_ci    client.write(`GET ${str} ${end}`);
591cb0ef41Sopenharmony_ci    client.write(`GET / ${end}`);
601cb0ef41Sopenharmony_ci    client.write(`GET / ${end}`);
611cb0ef41Sopenharmony_ci    client.end();
621cb0ef41Sopenharmony_ci  });
631cb0ef41Sopenharmony_ci});
64