1'use strict'; 2 3require('../common'); 4const http = require('http'); 5const net = require('net'); 6const url = require('url'); 7const assert = require('assert'); 8const Countdown = require('../common/countdown'); 9 10// Response splitting example, credit: Amit Klein, Safebreach 11const str = '/welcome?lang=bar%c4%8d%c4%8aContentLength:%200%c4%8d%c4%8a%c' + 12 '4%8d%c4%8aHTTP/1.1%20200%20OK%c4%8d%c4%8aContentLength:%202' + 13 '0%c4%8d%c4%8aLastModified:%20Mon,%2027%20Oct%202003%2014:50:18' + 14 '%20GMT%c4%8d%c4%8aContentType:%20text/html%c4%8d%c4%8a%c4%8' + 15 'd%c4%8a%3chtml%3eGotcha!%3c/html%3e'; 16 17// Response splitting example, credit: Сковорода Никита Андреевич (@ChALkeR) 18const x = 'fooഊSet-Cookie: foo=barഊഊ<script>alert("Hi!")</script>'; 19const y = 'foo⠊Set-Cookie: foo=bar'; 20 21let count = 0; 22const countdown = new Countdown(3, () => server.close()); 23 24function test(res, code, key, value) { 25 const header = { [key]: value }; 26 assert.throws( 27 () => res.writeHead(code, header), 28 { 29 code: 'ERR_INVALID_CHAR', 30 name: 'TypeError', 31 message: `Invalid character in header content ["${key}"]` 32 } 33 ); 34} 35 36const server = http.createServer((req, res) => { 37 switch (count++) { 38 case 0: { 39 const loc = url.parse(req.url, true).query.lang; 40 test(res, 302, 'Location', `/foo?lang=${loc}`); 41 break; 42 } 43 case 1: 44 test(res, 200, 'foo', x); 45 break; 46 case 2: 47 test(res, 200, 'foo', y); 48 break; 49 default: 50 assert.fail('should not get to here.'); 51 } 52 countdown.dec(); 53 res.end('ok'); 54}); 55server.listen(0, () => { 56 const end = 'HTTP/1.1\r\n\r\n'; 57 const client = net.connect({ port: server.address().port }, () => { 58 client.write(`GET ${str} ${end}`); 59 client.write(`GET / ${end}`); 60 client.write(`GET / ${end}`); 61 client.end(); 62 }); 63}); 64