Browse Source

Fix a bug in HTTP server when receiving half-closes.

v0.7.4-release
Ryan 16 years ago
parent
commit
6a172d7119
  1. 28
      src/http.js
  2. 2
      src/net.cc
  3. 25
      test/test-http.js
  4. 17
      test/test-pingpong.js
  5. 23
      test_client.js

28
src/http.js

@ -105,6 +105,7 @@ function toRaw(string) {
node.http.ServerResponse = function (connection, responses) {
responses.push(this);
this.connection = connection;
this.closeOnFinish = false;
var output = [];
// The send method appends data onto the output array. The deal is,
@ -151,14 +152,7 @@ node.http.ServerResponse = function (connection, responses) {
output.push(data);
};
this.flush = function () {
if (responses.length > 0 && responses[0] === this)
while (output.length > 0)
connection.send(output.shift());
};
var chunked_encoding = false;
var connection_close = false;
this.sendHeader = function (status_code, headers) {
var sent_connection_header = false;
@ -225,6 +219,14 @@ node.http.ServerResponse = function (connection, responses) {
this.flush();
};
this.flush = function () {
if (responses.length > 0 && responses[0] === this)
while (output.length > 0) {
var out = output.shift();
connection.send(out);
}
};
this.finished = false;
this.finish = function () {
if (chunked_encoding)
@ -235,11 +237,9 @@ node.http.ServerResponse = function (connection, responses) {
while (responses.length > 0 && responses[0].finished) {
var res = responses[0];
res.flush();
responses.shift();
}
if (responses.length == 0 && connection_close) {
if (res.closeOnFinish)
connection.fullClose();
responses.shift();
}
};
};
@ -322,7 +322,11 @@ node.http.Server = function (RequestHandler, options) {
// is this really needed?
connection.onEOF = function () {
puts("HTTP SERVER got eof");
if (responses.length == 0)
connection.close();
else
responses[responses.length-1].closeOnFinish = true;
};
}
@ -355,7 +359,7 @@ node.http.Client = function (port, host) {
if (connection_expression.exec(field)) {
sent_connection_header = true;
if (close_expression.exec(value))
connection_close = true;
this.closeOnFinish = true;
} else if (transfer_encoding_expression.exec(field)) {
sent_transfer_encoding_header = true;
if (chunk_expression.exec(value))

2
src/net.cc

@ -440,7 +440,7 @@ void name () \
TryCatch try_catch; \
callback->Call(handle_, 0, NULL); \
if (try_catch.HasCaught()) \
fatal_exception(try_catch); \
node::fatal_exception(try_catch); \
}
DEFINE_SIMPLE_CALLBACK(Connection::OnConnect, ON_CONNECT_SYMBOL)

25
test/test-http.js

@ -7,24 +7,26 @@ function onLoad() {
var request_number = 0;
new node.http.Server(function (req, res) {
var server = this;
res.id = request_number;
req.id = request_number++;
if (req.id == 0) {
puts("get req");
//puts("get req");
assertEquals("GET", req.method);
assertEquals("/hello", req.uri.path);
}
if (req.id == 1) {
puts("post req");
//puts("post req");
assertEquals("POST", req.method);
assertEquals("/quit", req.uri.path);
server.close();
puts("server closed");
this.close();
//puts("server closed");
}
setTimeout(function () {
//puts("send response");
res.sendHeader(200, [["Content-Type", "text/plain"]]);
res.sendBody(req.uri.path);
res.finish();
@ -35,13 +37,14 @@ function onLoad() {
var c = new node.tcp.Connection();
var req_sent = 0;
c.onConnect = function () {
puts("send get");
//puts("send get");
c.send( "GET /hello HTTP/1.1\r\n\r\n" );
req_sent += 1;
};
var total = "";
c.onReceive = function (chunk) {
//puts("client recv");
total += chunk.encodeUtf8();
puts("total: " + JSON.stringify(total));
@ -49,12 +52,20 @@ function onLoad() {
puts("send post");
c.send("POST /quit HTTP/1.1\r\n\r\n");
c.close();
puts("client half close");
assertEquals(c.readyState, "readOnly");
req_sent += 1;
}
};
c.onEOF = function () {
puts("client got eof");
};
c.onDisconnect = function () {
puts("client disocnnected");
puts("client disconnected");
assertEquals(c.readyState, "closed");
var hello = new RegExp("/hello");
assertTrue(hello.exec(total) != null);

17
test/test-pingpong.js

@ -48,23 +48,34 @@ function onLoad() {
client.send("PING");
};
var sent_final_ping = false;
client.onReceive = function (data) {
assertEquals("open", client.readyState);
//puts("client recved data: " + JSON.stringify(data));
stdout.print(".");
assertEquals("PONG", data);
count += 1;
if (sent_final_ping) {
assertEquals("readOnly", client.readyState);
return;
} else {
assertEquals("open", client.readyState);
}
if (count < N) {
client.send("PING");
} else {
puts("sending FIN");
puts("sending final ping");
sent_final_ping = true;
client.send("PING");
client.close();
}
};
client.onEOF = function () {
puts("pinger: onEOF");
assertEquals(N, count);
assertEquals(N+1, count);
};
client.connect(port);

23
test_client.js

@ -2,15 +2,32 @@ var c = new node.http.Client(8000, "localhost")
var req = c.get("/hello/world", [["Accept", "*/*"]]);
req.finish(function (res) {
puts("got response: " + res.status_code.toString());
puts("response 1: " + res.status_code.toString());
res.onBody = function (chunk) {
puts("got response body <" + chunk.encodeUtf8() + ">");
puts("response 1 body <" + chunk.encodeUtf8() + ">");
return true;
};
res.onBodyComplete = function () {
puts("response complete!");
puts("response 1 complete!");
return true;
};
});
/*
var req = c.get("/something/else", []);
req.finish(function (res) {
puts("response 2: " + res.status_code.toString());
res.onBody = function (chunk) {
puts("response 2 body <" + chunk.encodeUtf8() + ">");
return true;
};
res.onBodyComplete = function () {
puts("response 2 complete!");
return true;
};
});
*/

Loading…
Cancel
Save