11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ci// Response splitting is no longer an issue with HTTP/2. The underlying
41cb0ef41Sopenharmony_ci// nghttp2 implementation automatically strips out the header values that
51cb0ef41Sopenharmony_ci// contain invalid characters.
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst common = require('../common');
81cb0ef41Sopenharmony_ciif (!common.hasCrypto)
91cb0ef41Sopenharmony_ci  common.skip('missing crypto');
101cb0ef41Sopenharmony_ciconst assert = require('assert');
111cb0ef41Sopenharmony_ciconst http2 = require('http2');
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci// Response splitting example, credit: Amit Klein, Safebreach
141cb0ef41Sopenharmony_ciconst str = '/welcome?lang=bar%c4%8d%c4%8aContent­Length:%200%c4%8d%c4%8a%c' +
151cb0ef41Sopenharmony_ci            '4%8d%c4%8aHTTP/1.1%20200%20OK%c4%8d%c4%8aContent­Length:%202' +
161cb0ef41Sopenharmony_ci            '0%c4%8d%c4%8aLast­Modified:%20Mon,%2027%20Oct%202003%2014:50:18' +
171cb0ef41Sopenharmony_ci            '%20GMT%c4%8d%c4%8aContent­Type:%20text/html%c4%8d%c4%8a%c4%8' +
181cb0ef41Sopenharmony_ci            'd%c4%8a%3chtml%3eGotcha!%3c/html%3e';
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci// Response splitting example, credit: Сковорода Никита Андреевич (@ChALkeR)
211cb0ef41Sopenharmony_ciconst x = 'fooഊSet-Cookie: foo=barഊഊ<script>alert("Hi!")</script>';
221cb0ef41Sopenharmony_ciconst y = 'foo⠊Set-Cookie: foo=bar';
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_cilet remaining = 3;
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_cifunction makeUrl(headers) {
271cb0ef41Sopenharmony_ci  return `${headers[':scheme']}://${headers[':authority']}${headers[':path']}`;
281cb0ef41Sopenharmony_ci}
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciconst server = http2.createServer();
311cb0ef41Sopenharmony_ciserver.on('stream', common.mustCall((stream, headers) => {
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci  const obj = Object.create(null);
341cb0ef41Sopenharmony_ci  switch (remaining--) {
351cb0ef41Sopenharmony_ci    case 3: {
361cb0ef41Sopenharmony_ci      const url = new URL(makeUrl(headers));
371cb0ef41Sopenharmony_ci      obj[':status'] = 302;
381cb0ef41Sopenharmony_ci      obj.Location = `/foo?lang=${url.searchParams.get('lang')}`;
391cb0ef41Sopenharmony_ci      break;
401cb0ef41Sopenharmony_ci    }
411cb0ef41Sopenharmony_ci    case 2:
421cb0ef41Sopenharmony_ci      obj.foo = x;
431cb0ef41Sopenharmony_ci      break;
441cb0ef41Sopenharmony_ci    case 1:
451cb0ef41Sopenharmony_ci      obj.foo = y;
461cb0ef41Sopenharmony_ci      break;
471cb0ef41Sopenharmony_ci  }
481cb0ef41Sopenharmony_ci  stream.respond(obj);
491cb0ef41Sopenharmony_ci  stream.end();
501cb0ef41Sopenharmony_ci}, 3));
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ciserver.listen(0, common.mustCall(() => {
531cb0ef41Sopenharmony_ci  const client = http2.connect(`http://localhost:${server.address().port}`);
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  function maybeClose() {
561cb0ef41Sopenharmony_ci    if (remaining === 0) {
571cb0ef41Sopenharmony_ci      server.close();
581cb0ef41Sopenharmony_ci      client.close();
591cb0ef41Sopenharmony_ci    }
601cb0ef41Sopenharmony_ci  }
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci  function doTest(path, key, expected) {
631cb0ef41Sopenharmony_ci    const req = client.request({ ':path': path });
641cb0ef41Sopenharmony_ci    req.on('response', common.mustCall((headers) => {
651cb0ef41Sopenharmony_ci      assert.strictEqual(headers.foo, undefined);
661cb0ef41Sopenharmony_ci      assert.strictEqual(headers.location, undefined);
671cb0ef41Sopenharmony_ci    }));
681cb0ef41Sopenharmony_ci    req.resume();
691cb0ef41Sopenharmony_ci    req.on('end', common.mustCall());
701cb0ef41Sopenharmony_ci    req.on('close', common.mustCall(maybeClose));
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  doTest(str, 'location', str);
741cb0ef41Sopenharmony_ci  doTest('/', 'foo', x);
751cb0ef41Sopenharmony_ci  doTest('/', 'foo', y);
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci}));
78