var content_length = body.length.toString();
res.sendHeader( status
- , [ ["Content-Type", "text/plain"]
- , ["Content-Length", content_length]
- ]
+ , { "Content-Type": "text/plain"
+ , "Content-Length": content_length
+ }
);
res.sendBody(body);
}
var server = node.http.createServer(function (req, res) {
- res.sendHeader(200, [
- ["Content-Type", "text/plain"],
- ["Content-Length", body.length]
- ]);
+ res.sendHeader(200, {
+ "Content-Type": "text/plain",
+ "Content-Length": body.length
+ });
res.sendBody(body);
res.finish();
})
this.connection = connection;
this.httpVersion = null;
- this.headers = [];
+ this.headers = {};
// request (server) only
this.uri = "";
this.connection.readResume();
};
+IncomingMessage.prototype._addHeaderLine = function (field, value) {
+ if (field in this.headers) {
+ // TODO Certain headers like 'Content-Type' should not be concatinated.
+ // See https://www.google.com/reader/view/?tab=my#overview-page
+ this.headers[field] += ", " + value;
+ } else {
+ this.headers[field] = value;
+ }
+};
function OutgoingMessage () {
node.EventEmitter.call(this);
this.output.push(data);
};
-OutgoingMessage.prototype.sendHeaderLines = function (first_line, header_lines) {
+OutgoingMessage.prototype.sendHeaderLines = function (first_line, headers) {
var sent_connection_header = false;
var sent_content_length_header = false;
var sent_transfer_encoding_header = false;
- header_lines = header_lines || [];
-
// first_line in the case of request is: "GET /index.html HTTP/1.1\r\n"
// in the case of response it is: "HTTP/1.1 200 OK\r\n"
- var header = first_line;
-
- for (var i = 0; i < header_lines.length; i++) {
- var field = header_lines[i][0];
- var value = header_lines[i][1];
+ var message_header = first_line;
+ var field, value;
+ for (var i in headers) {
+ if (headers instanceof Array) {
+ field = headers[i][0];
+ value = headers[i][1];
+ } else {
+ if (!headers.hasOwnProperty(i)) continue;
+ field = i;
+ value = headers[i];
+ }
- header += field + ": " + value + CRLF;
+ message_header += field + ": " + value + CRLF;
if (connection_expression.exec(field)) {
sent_connection_header = true;
// keep-alive logic
if (sent_connection_header == false) {
if (this.should_keep_alive) {
- header += "Connection: keep-alive\r\n";
+ message_header += "Connection: keep-alive\r\n";
} else {
this.closeOnFinish = true;
- header += "Connection: close\r\n";
+ message_header += "Connection: close\r\n";
}
}
if (sent_content_length_header == false && sent_transfer_encoding_header == false) {
if (this.use_chunked_encoding_by_default) {
- header += "Transfer-Encoding: chunked\r\n";
+ message_header += "Transfer-Encoding: chunked\r\n";
this.chunked_encoding = true;
}
}
- header += CRLF;
+ message_header += CRLF;
- this.send(header);
+ this.send(message_header);
// wait until the first body chunk, or finish(), is sent to flush.
};
};
-function ClientRequest (method, uri, header_lines) {
+function ClientRequest (method, uri, headers) {
OutgoingMessage.call(this);
this.should_keep_alive = false;
}
this.closeOnFinish = true;
- this.sendHeaderLines(method + " " + uri + " HTTP/1.1\r\n", header_lines);
+ this.sendHeaderLines(method + " " + uri + " HTTP/1.1\r\n", headers);
}
node.inherits(ClientRequest, OutgoingMessage);
stream.addListener("incoming", incoming_listener);
var incoming;
- var last_header_was_a_value = false;
+ var field = null, value = null;
connection.addListener("message_begin", function () {
incoming = new IncomingMessage(connection);
});
connection.addListener("header_field", function (data) {
- if (incoming.headers.length > 0 && last_header_was_a_value == false) {
- incoming.headers[incoming.headers.length-1][0] += data;
+ if (value) {
+ incoming._addHeaderLine(field, value);
+ field = null;
+ value = null;
+ }
+ if (field) {
+ field += data;
} else {
- incoming.headers.push([data]);
+ field = data;
}
- last_header_was_a_value = false;
});
connection.addListener("header_value", function (data) {
- var last_pair = incoming.headers[incoming.headers.length-1];
- if (last_pair.length == 1) {
- last_pair[1] = data;
- } else {
- last_pair[1] += data;
- }
- last_header_was_a_value = true;
+ if (value) {
+ value += data;
+ } else {
+ value = data;
+ }
});
connection.addListener("headers_complete", function (info) {
+ if (field && value) {
+ incoming._addHeaderLine(field, value);
+ }
+
incoming.httpVersion = info.httpVersion;
if (info.method) {
var response_body = '{"ok": true}';
var server = node.http.createServer(function(req, res) {
- res.sendHeader(200, [['Content-Type', 'text/javascript']]);
+ res.sendHeader(200, {'Content-Type': 'text/javascript'});
res.sendBody(response_body);
res.finish();
});
var server = node.http.createServer(function (req, res) {
var body = req.uri.path === "/1" ? body1_s : body2_s;
- res.sendHeader(200, [
- ["Content-Type", "text/plain"],
- ["Content-Length", body.length]
- ]);
+ res.sendHeader(200, { "Content-Type": "text/plain"
+ , "Content-Length": body.length
+ });
res.sendBody(body);
res.finish();
});
req.addListener("complete", function () {
server_req_complete = true;
puts("request complete from server");
- res.sendHeader(200, [['Content-Type', 'text/plain']]);
+ res.sendHeader(200, {'Content-Type': 'text/plain'});
res.sendBody('hello\n');
res.finish();
});
var backend = node.http.createServer(function (req, res) {
// node.debug("backend");
- res.sendHeader(200, [["content-type", "text/plain"]]);
+ res.sendHeader(200, {"content-type": "text/plain"});
res.sendBody("hello world\n");
res.finish();
});
var proxy_client = node.http.createClient(BACKEND_PORT);
var proxy = node.http.createServer(function (req, res) {
- // node.debug("proxy req");
+ node.debug("proxy req headers: " + JSON.stringify(req.headers));
var proxy_req = proxy_client.get(req.uri.path);
proxy_req.finish(function(proxy_res) {
res.sendHeader(proxy_res.statusCode, proxy_res.headers);
}
setTimeout(function () {
- res.sendHeader(200, [["Content-Type", "text/plain"]]);
+ res.sendHeader(200, {"Content-Type": "text/plain"});
res.sendBody(req.uri.path);
res.finish();
}, 1);
if (responses_sent == 0) {
assertEquals("GET", req.method);
assertEquals("/hello", req.uri.path);
+
+ p(req.headers);
+ assertTrue("Accept" in req.headers);
+ assertEquals("*/*", req.headers["Accept"]);
+
+ assertTrue("Foo" in req.headers);
+ assertEquals("bar", req.headers["Foo"]);
}
if (responses_sent == 1) {
}
req.addListener("complete", function () {
- res.sendHeader(200, [["Content-Type", "text/plain"]]);
+ res.sendHeader(200, {"Content-Type": "text/plain"});
res.sendBody("The path was " + req.uri.path);
res.finish();
responses_sent += 1;
}).listen(PORT);
var client = node.http.createClient(PORT);
- var req = client.get("/hello");
+ var req = client.get("/hello", {"Accept": "*/*", "Foo": "bar"});
req.finish(function (res) {
assertEquals(200, res.statusCode);
responses_recvd += 1;
----------------------------------------
node.http.createServer(function (request, response) {
setTimeout(function () {
- response.sendHeader(200, [["Content-Type", "text/plain"]]);
+ response.sendHeader(200, {"Content-Type": "text/plain"});
response.sendBody("Hello World");
response.finish();
}, 2000);
careful to never buffer entire requests or responses--the
user is able to stream data.
-HTTP message headers are represented by an array of 2-element
-arrays like this
+HTTP message headers are represented by an object like this
----------------------------------------
- [ ["Content-Length", "123"]
- , ["Content-Type", "text/plain"]
- , ["Connection", "keep-alive"]
- , ["Accept", "*/*"]
- ]
+ { "Content-Length": "123"
+ , "Content-Type": "text/plain"
+ , "Connection": "keep-alive"
+ , "Accept": "*/*"
+ }
----------------------------------------
In order to support the full spectrum of possible HTTP applications, Node's
+request.headers+ ::
-The request headers expressed as an array of 2-element arrays.
Read only.
+response.sendHeader(statusCode, headers)+ ::
Sends a response header to the request. The status code is a 3-digit HTTP
-status code, like +404+. The second argument, +headers+, should be an array
-of 2-element arrays, representing the response headers.
+status code, like +404+. The second argument, +headers+ are the response headers.
+
Example:
+
----------------------------------------
var body = "hello world";
-response.sendHeader(200, [
- ["Content-Length", body.length],
- ["Content-Type", "text/plain"]
-]);
+response.sendHeader(200, {
+ "Content-Length": body.length,
+ "Content-Type": "text/plain"
+});
----------------------------------------
+
This method must only be called once on a message and it must
Issues a request; if necessary establishes connection. Returns a +node.http.ClientRequest+ instance.
+
+request_headers+ is optional.
-+request_headers+ should be an array of 2-element
-arrays. Additional request headers might be added internally
+Additional request headers might be added internally
by Node. Returns a +ClientRequest+ object.
+
Do remember to include the +Content-Length+ header if you
+"1.1"+ or +"1.0"+.
+response.headers+ ::
- The response headers. An Array of 2-element arrays.
+ The response headers.
+response.setBodyEncoding(encoding)+ ::
Set the encoding for the response body. Either +"utf8"+ or +"raw"+.
<pre>
node.http.createServer(function (req, res) {
setTimeout(function () {
- res.sendHeader(200, [["Content-Type", "text/plain"]]);
+ res.sendHeader(200, {"Content-Type": "text/plain"});
res.sendBody("Hello World");
res.finish();
}, 2000);