Skip to content
This repository has been archived by the owner on May 5, 2023. It is now read-only.

Resume the client socket when it is unpiped #14

Merged
merged 3 commits into from
Oct 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
sudo: false
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


language: node_js

node_js:
Expand All @@ -8,6 +6,8 @@ node_js:
- "6"
- "7"
- "8"
- "10"
- "12"

install:
- PATH="`npm bin`:`npm bin -g`:$PATH"
Expand Down
16 changes: 13 additions & 3 deletions proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,7 @@ function onconnect (req, socket, head) {
res.removeListener('finish', onfinish);

res.writeHead(200, 'Connection established');

// HACK: force a flush of the HTTP header
res._send('');
res.flushHeaders();

// relinquish control of the `socket` from the ServerResponse instance
res.detachSocket(socket);
Expand All @@ -351,6 +349,7 @@ function onconnect (req, socket, head) {
res = null;

socket.pipe(target);
target.once('unpipe', resume);
target.pipe(socket);
}

Expand Down Expand Up @@ -416,6 +415,17 @@ function onconnect (req, socket, head) {
});
}

/**
* Resumes a socket.
*
* @param {(net.Socket|tls.Socket)} socket The socket to resume
* @api private
*/

function resume (socket) {
socket.resume();
}

/**
* Checks `Proxy-Authorization` request headers. Same logic applied to CONNECT
* requests as well as regular HTTP requests.
Expand Down
42 changes: 42 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,48 @@ describe('proxy', function () {
});
});

it('should resume the client socket when it is unpiped', function (done) {
server.once('request', function (req, res) {
res.end();
});

var gotData = false;
var host = '127.0.0.1:' + serverPort;
var socket = net.connect({ port: proxyPort });

socket.on('connect', function () {
socket.write(
'CONNECT ' + host + ' HTTP/1.1\r\n' +
'Host: ' + host + '\r\n' +
'\r\n'
);
});

socket.on('close', function () {
assert(gotData);
done();
});

socket.setEncoding('utf8');
socket.once('data', function (data) {
assert(0 == data.indexOf('HTTP/1.1 200 Connection established\r\n'));

socket.write(
'POST / HTTP/1.1\r\n' +
'Host: ' + host + '\r\n' +
'Connection: close\r\n' +
'Transfer-Encoding: chunked\r\n' +
'\r\n'
);

socket.once('data', function (data) {
assert(0 == data.indexOf('HTTP/1.1 200 OK\r\n'));
gotData = true;
socket.write('10\r\n{ "foo": "bar",\r\n');
});
});
});


describe('authentication', function () {
function clearAuth () {
Expand Down