Skip to content

Commit b27f8ba

Browse files
committed
Default to chunked for client requests without C-Length.
Also add test. Reported by Felix Geisendörfer.
1 parent 2ebd692 commit b27f8ba

File tree

2 files changed

+74
-18
lines changed

2 files changed

+74
-18
lines changed

src/http.js

+22-18
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,6 @@ function OutgoingMessage () {
140140

141141
this.output = [];
142142

143-
this.sent_connection_header = false;
144-
this.sent_content_length_header = false;
145-
this.sent_transfer_encoding_header = false;
146-
147143
this.closeOnFinish = false;
148144
this.chunked_encoding = false;
149145
this.should_keep_alive = true;
@@ -159,6 +155,10 @@ OutgoingMessage.prototype.send = function (data, encoding) {
159155
};
160156

161157
OutgoingMessage.prototype.sendHeaderLines = function (first_line, header_lines) {
158+
var sent_connection_header = false;
159+
var sent_content_length_header = false;
160+
var sent_transfer_encoding_header = false;
161+
162162
header_lines = header_lines || [];
163163

164164
// first_line in the case of request is: "GET /index.html HTTP/1.1\r\n"
@@ -172,21 +172,21 @@ OutgoingMessage.prototype.sendHeaderLines = function (first_line, header_lines)
172172
header += field + ": " + value + CRLF;
173173

174174
if (connection_expression.exec(field)) {
175-
this.sent_connection_header = true;
175+
sent_connection_header = true;
176176
if (close_expression.exec(value)) this.closeOnFinish = true;
177177

178178
} else if (transfer_encoding_expression.exec(field)) {
179-
this.sent_transfer_encoding_header = true;
179+
sent_transfer_encoding_header = true;
180180
if (chunk_expression.exec(value)) this.chunked_encoding = true;
181181

182182
} else if (content_length_expression.exec(field)) {
183-
this.sent_content_length_header = true;
183+
sent_content_length_header = true;
184184

185185
}
186186
}
187187

188188
// keep-alive logic
189-
if (this.sent_connection_header == false) {
189+
if (sent_connection_header == false) {
190190
if (this.should_keep_alive) {
191191
header += "Connection: keep-alive\r\n";
192192
} else {
@@ -195,7 +195,7 @@ OutgoingMessage.prototype.sendHeaderLines = function (first_line, header_lines)
195195
}
196196
}
197197

198-
if (this.sent_content_length_header == false && this.sent_transfer_encoding_header == false) {
198+
if (sent_content_length_header == false && sent_transfer_encoding_header == false) {
199199
if (this.use_chunked_encoding_by_default) {
200200
header += "Transfer-Encoding: chunked\r\n";
201201
this.chunked_encoding = true;
@@ -251,7 +251,11 @@ function ClientRequest (method, uri, header_lines) {
251251
OutgoingMessage.call(this);
252252

253253
this.should_keep_alive = false;
254-
this.use_chunked_encoding_by_default = false;
254+
if (method === "GET" || method === "HEAD") {
255+
this.use_chunked_encoding_by_default = false;
256+
} else {
257+
this.use_chunked_encoding_by_default = true;
258+
}
255259
this.closeOnFinish = true;
256260

257261
this.sendHeaderLines(method + " " + uri + " HTTP/1.1\r\n", header_lines);
@@ -329,7 +333,7 @@ function createIncomingMessageStream (connection, incoming_listener) {
329333
/* Returns true if the message queue is finished and the connection
330334
* should be closed. */
331335
function flushMessageQueue (connection, queue) {
332-
if (connection.readyState === "closed" || connection.readyState === "readOnly") {
336+
if (connection.readyState !== "open" && connection.readyState !== "writeOnly") {
333337
return false;
334338
}
335339

@@ -374,18 +378,17 @@ function connectionListener (connection) {
374378
}
375379
});
376380

377-
var flushResponse = function () {
378-
if(flushMessageQueue(connection, responses)) {
379-
connection.fullClose();
380-
}
381-
};
382381

383382
createIncomingMessageStream(connection, function (incoming, should_keep_alive) {
384383
var req = incoming;
385384

386385
var res = new ServerResponse(connection);
387386
res.should_keep_alive = should_keep_alive;
388-
res.addListener("flush", flushResponse);
387+
res.addListener("flush", function () {
388+
if(flushMessageQueue(connection, responses)) {
389+
connection.fullClose();
390+
}
391+
});
389392
responses.push(res);
390393

391394
connection.server.emit("request", [req, res]);
@@ -405,6 +408,7 @@ node.http.createClient = function (port, host) {
405408
client.connect(port, host); // reconnect
406409
return;
407410
}
411+
//node.debug("client flush readyState = " + client.readyState);
408412
if (req == requests[0]) flushMessageQueue(client, [req]);
409413
});
410414
requests.push(req);
@@ -437,7 +441,7 @@ node.http.createClient = function (port, host) {
437441
});
438442

439443
createIncomingMessageStream(client, function (res) {
440-
//node.debug("incoming response!");
444+
//node.debug("incoming response!");
441445

442446
res.addListener("complete", function ( ) {
443447
//node.debug("request complete disconnecting. readyState = " + client.readyState);
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
include("mjsunit.js");
2+
var PORT = 18032;
3+
4+
var sent_body = "";
5+
var server_req_complete = false;
6+
var client_res_complete = false;
7+
8+
var server = node.http.createServer(function(req, res) {
9+
assertEquals("POST", req.method);
10+
req.setBodyEncoding("utf8");
11+
12+
req.addListener("body", function (chunk) {
13+
puts("server got: " + JSON.stringify(chunk));
14+
sent_body += chunk;
15+
});
16+
17+
req.addListener("complete", function () {
18+
server_req_complete = true;
19+
puts("request complete from server");
20+
res.sendHeader(200, [['Content-Type', 'text/plain']]);
21+
res.sendBody('hello\n');
22+
res.finish();
23+
});
24+
});
25+
server.listen(PORT);
26+
27+
function onLoad () {
28+
var client = node.http.createClient(PORT);
29+
var req = client.post('/');
30+
31+
req.sendBody('1\n');
32+
req.sendBody('2\n');
33+
req.sendBody('3\n');
34+
35+
puts("client finished sending request");
36+
req.finish(function(res) {
37+
res.setBodyEncoding("utf8");
38+
res.addListener('body', function(chunk) {
39+
puts(chunk);
40+
});
41+
res.addListener('complete', function() {
42+
client_res_complete = true;
43+
server.close();
44+
});
45+
});
46+
}
47+
48+
function onExit () {
49+
assertEquals("1\n2\n3\n", sent_body);
50+
assertTrue(server_req_complete);
51+
assertTrue(client_res_complete);
52+
}

0 commit comments

Comments
 (0)