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%8aContentLength:%200%c4%8d%c4%8a%c' + 151cb0ef41Sopenharmony_ci '4%8d%c4%8aHTTP/1.1%20200%20OK%c4%8d%c4%8aContentLength:%202' + 161cb0ef41Sopenharmony_ci '0%c4%8d%c4%8aLastModified:%20Mon,%2027%20Oct%202003%2014:50:18' + 171cb0ef41Sopenharmony_ci '%20GMT%c4%8d%c4%8aContentType:%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