|
const net = require('net'); |
|
const dns = require('dns'); |
|
const request = require('request'); |
|
|
|
const start = Date.now(); |
|
|
|
function log() { |
|
const time = (Date.now() - start).toString(); |
|
console.log.apply(console, [time].concat(Array.from(arguments))); |
|
} |
|
|
|
function delay(func, msecs) { |
|
return function () { |
|
const args = arguments; |
|
setTimeout(() => { |
|
func.apply(this, args); |
|
}, msecs); |
|
}; |
|
} |
|
|
|
function isRequestEnd(str) { |
|
const len = str.length; |
|
if (len < 4) { |
|
return false; |
|
} |
|
return str[len - 4] === '\r' && |
|
str[len - 3] === '\n' && |
|
str[len - 2] === '\r' && |
|
str[len - 1] === '\n'; |
|
} |
|
|
|
const server = net.createServer((socket) => { |
|
let buffer = ''; |
|
socket.setEncoding('utf8'); |
|
socket.on('data', (chunk) => { |
|
buffer += chunk; |
|
if (isRequestEnd(buffer)) { |
|
log('[server]', buffer); |
|
setTimeout(() => { |
|
socket.write('HTTP/1.1 200 OK\r\n'); |
|
setTimeout(() => { |
|
socket.write('Content-Length: 5\r\n'); |
|
socket.write('\r\n'); |
|
socket.write('hello'); |
|
socket.end(); |
|
}, 200); |
|
}, 200); |
|
} |
|
}); |
|
}); |
|
|
|
server.listen(() => { |
|
const port = server.address().port; |
|
log('[server] Listening on', port); |
|
|
|
// Don't specify `path` with `createConnection` because it tries to |
|
// connect to the domain socket specified by the `path`. |
|
const req = request({ |
|
port: port, |
|
url: `http://localhost:${port}/`, |
|
// Cannot have delay on net.createConnection easily because it has to return |
|
// a socket synchronously. |
|
// createConnection: net.createConnection, |
|
lookup: delay(dns.lookup, 200), |
|
timeout: 250, |
|
// timeout: 150, |
|
}, (error, res, body) => { |
|
if (error) { |
|
log('[client] error:', error); |
|
server.close(); |
|
return; |
|
} |
|
log('[client]', res.statusCode, res.headers); |
|
log('[client]', body); |
|
server.close(); |
|
}); |
|
req.end(); |
|
log('[client] making request'); |
|
}); |