Skip to content

Commit

Permalink
http: add test, fix write after end
Browse files Browse the repository at this point in the history
  • Loading branch information
fatal10110 committed Sep 12, 2021
1 parent 6413200 commit 12d6866
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 24 deletions.
55 changes: 31 additions & 24 deletions lib/_http_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -907,39 +907,46 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
resOnFinish.bind(undefined,
req, res, socket, state, server));

if (typeof server.maxRequestsPerSocket === 'number'
&& (req.httpVersionMajor === 1 && req.httpVersionMinor === 1)) {
let handled = false;

if (server.maxRequestsPerSocket < ++state.requestsCount) {
res.writeHead(503);
res.end();
if (req.httpVersionMajor === 1 && req.httpVersionMinor === 1) {
if (typeof server.maxRequestsPerSocket === 'number') {
state.requestsCount++
res.shouldKeepAlive = server.maxRequestsPerSocket > state.requestsCount
}

res.shouldKeepAlive = server.maxRequestsPerSocket > state.requestsCount
}

if (req.headers.expect !== undefined &&
(req.httpVersionMajor === 1 && req.httpVersionMinor === 1)) {
if (RegExpPrototypeTest(continueExpression, req.headers.expect)) {
res._expect_continue = true;

if (server.listenerCount('checkContinue') > 0) {
server.emit('checkContinue', req, res);
if (typeof server.maxRequestsPerSocket === 'number'
&& (server.maxRequestsPerSocket < state.requestsCount)) {
handled = true

res.writeHead(503);
res.end();
} else if (req.headers.expect !== undefined) {
handled = true

if (RegExpPrototypeTest(continueExpression, req.headers.expect)) {
res._expect_continue = true;

if (server.listenerCount('checkContinue') > 0) {
server.emit('checkContinue', req, res);
} else {
res.writeContinue();
server.emit('request', req, res);
}
} else if (server.listenerCount('checkExpectation') > 0) {
server.emit('checkExpectation', req, res);
} else {
res.writeContinue();
server.emit('request', req, res);
res.writeHead(417);
res.end();
}
} else if (server.listenerCount('checkExpectation') > 0) {
server.emit('checkExpectation', req, res);
} else {
res.writeHead(417);
res.end();
}
} else {
req.on('end', clearRequestTimeout);
}

if(!handled) {
req.on('end', clearRequestTimeout);
server.emit('request', req, res);
}

return 0; // No special treatment.
}

Expand Down
85 changes: 85 additions & 0 deletions test/parallel/test-http-keep-alive-max-requests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
'use strict';

const net = require('net');
const http = require('http');
const assert = require('assert');
const common = require('../common');

const server = http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('Hello World!');
res.end();
})

function assertResponse(headers, body, expectClosed) {
if (expectClosed) {
assert.match(responses[4], /Connection: close\r\n/m);
assert(responses[4].search(/Keep-Alive: timeout=5, max=3\r\n/m) === -1);
assert.match(responses[5], /Hello World!/m);
} else {
assert.match(headers, /Connection: keep-alive\r\n/m);
assert.match(headers, /Keep-Alive: timeout=5, max=3\r\n/m);
assert.match(body, /Hello World!/m);
}
}

function writeRequest(socket) {
socket.write('GET / HTTP/1.1\r\n');
socket.write('Connection: keep-alive\r\n');
socket.write('\r\n\r\n')
}

server.maxRequestsPerSocket = 3;
server.listen(0, common.mustCall((res) => {
const socket = net.createConnection(
{ port: server.address().port },
common.mustCall(() => {
writeRequest(socket)
writeRequest(socket)

const anotherSocket = net.createConnection(
{ port: server.address().port },
common.mustCall(() => {
writeRequest(anotherSocket)
writeRequest(anotherSocket)

let anotherBuffer = ''

anotherSocket.setEncoding('utf8');
anotherSocket.on('data', common.mustCall((data) => {
anotherBuffer += data;
}));

anotherSocket.on('end', common.mustCall(() => {
const anoterResponses = anotherBuffer.trim().split('\r\n\r\n');

assertResponse(anoterResponses[0], anoterResponses[1], false)
assertResponse(anoterResponses[2], anoterResponses[3], false)

// Add two additional requests to two previous on the first socket
writeRequest(socket)
writeRequest(socket)

let buffer = '';
socket.setEncoding('utf8');
socket.on('data', common.mustCall((data) => {
buffer += data;
}));

socket.on('end', common.mustCall(() => {
const responses = buffer.trim().split('\r\n\r\n');
// We sent more requests than allowed per socket,
// but we get only the allowed number of responses & headers
assert(responses.length === server.maxRequestsPerSocket * 2);

assertResponse(responses[0], responses[1], false)
assertResponse(responses[2], responses[3], false)
assertResponse(responses[4], responses[5], true)

server.close();
}));
}));
}));
})
);
}));

0 comments on commit 12d6866

Please sign in to comment.