Browse Source

Don't use parseUri for HTTP server

The big parseUri RE was showing up often in profiles - this is simpler and
yields better performance by taking advantage of the C http parser.
v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
e2b7902469
  1. 21
      doc/api.txt
  2. 23
      lib/http.js
  3. 33
      src/http.cc
  4. 6
      src/http.h

21
doc/api.txt

@ -665,7 +665,7 @@ The request method as a string. Read only. Example:
+request.uri+ :: +request.uri+ ::
Request URI Object. This contains only the parameters that are Request URI Object. This contains only the parameters that are
present in the actual HTTP request. That is, if the request is present in the actual HTTP request. If the request is
+ +
---------------------------------------- ----------------------------------------
GET /status?name=ryan HTTP/1.1\r\n GET /status?name=ryan HTTP/1.1\r\n
@ -676,23 +676,12 @@ Accept: text/plain\r\n
Then +request.uri+ will be Then +request.uri+ will be
+ +
---------------------------------------- ----------------------------------------
{ path: "/status", { full: "/status?name=ryan",
file: "status", path: "/status",
directory: "/", queryString: "name=ryan",
params: { "name" : "ryan" } fragment: ""
} }
---------------------------------------- ----------------------------------------
+
In particular, note that +request.uri.protocol+ is
+undefined+. This is because there was no URI protocol given
in the actual HTTP Request.
+
Here is what's available: +request.uri.anchor+, +request.uri.query+,
+request.uri.file+, +request.uri.directory+, +request.uri.path+,
+request.uri.relative+, +request.uri.port+, +request.uri.host+,
+request.uri.password+, +request.uri.user+, +request.uri.authority+,
+request.uri.protocol+, +request.uri.params+, +request.uri.toString()+,
+request.uri.source+
+request.headers+ :: +request.headers+ ::

23
lib/http.js

@ -125,7 +125,13 @@ function IncomingMessage (connection) {
this.headers = {}; this.headers = {};
// request (server) only // request (server) only
this.uri = ""; this.uri = {
full: "",
queryString: "",
fragment: "",
path: ""
};
this.method = null; this.method = null;
// response (client) only // response (client) only
@ -338,7 +344,19 @@ function createIncomingMessageStream (connection, incoming_listener) {
// Only servers will get URI events. // Only servers will get URI events.
connection.addListener("uri", function (data) { connection.addListener("uri", function (data) {
incoming.uri += data; incoming.uri.full += data;
});
connection.addListener("path", function (data) {
incoming.uri.path += data;
});
connection.addListener("fragment", function (data) {
incoming.uri.fragment += data;
});
connection.addListener("queryString", function (data) {
incoming.uri.queryString += data;
}); });
connection.addListener("headerField", function (data) { connection.addListener("headerField", function (data) {
@ -372,7 +390,6 @@ function createIncomingMessageStream (connection, incoming_listener) {
if (info.method) { if (info.method) {
// server only // server only
incoming.method = info.method; incoming.method = info.method;
incoming.uri = exports.parseUri(incoming.uri); // TODO parse the URI lazily?
} else { } else {
// client only // client only
incoming.statusCode = info.statusCode; incoming.statusCode = info.statusCode;

33
src/http.cc

@ -95,6 +95,39 @@ HTTPConnection::on_uri (http_parser *parser, const char *buf, size_t len)
return 0; return 0;
} }
int
HTTPConnection::on_query_string (http_parser *parser, const char *buf, size_t len)
{
HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("queryString", 1, argv);
return 0;
}
int
HTTPConnection::on_path (http_parser *parser, const char *buf, size_t len)
{
HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("path", 1, argv);
return 0;
}
int
HTTPConnection::on_fragment (http_parser *parser, const char *buf, size_t len)
{
HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("fragment", 1, argv);
return 0;
}
int int
HTTPConnection::on_header_field (http_parser *parser, const char *buf, size_t len) HTTPConnection::on_header_field (http_parser *parser, const char *buf, size_t len)
{ {

6
src/http.h

@ -24,6 +24,9 @@ protected:
http_parser_init (&parser_, type); http_parser_init (&parser_, type);
parser_.on_message_begin = on_message_begin; parser_.on_message_begin = on_message_begin;
parser_.on_uri = on_uri; parser_.on_uri = on_uri;
parser_.on_path = on_path;
parser_.on_fragment = on_fragment;
parser_.on_query_string = on_query_string;
parser_.on_header_field = on_header_field; parser_.on_header_field = on_header_field;
parser_.on_header_value = on_header_value; parser_.on_header_value = on_header_value;
parser_.on_headers_complete = on_headers_complete; parser_.on_headers_complete = on_headers_complete;
@ -36,6 +39,9 @@ protected:
static int on_message_begin (http_parser *parser); static int on_message_begin (http_parser *parser);
static int on_uri (http_parser *parser, const char *at, size_t length); static int on_uri (http_parser *parser, const char *at, size_t length);
static int on_query_string (http_parser *parser, const char *at, size_t length);
static int on_path (http_parser *parser, const char *at, size_t length);
static int on_fragment (http_parser *parser, const char *at, size_t length);
static int on_header_field (http_parser *parser, const char *buf, size_t len); static int on_header_field (http_parser *parser, const char *buf, size_t len);
static int on_header_value (http_parser *parser, const char *buf, size_t len); static int on_header_value (http_parser *parser, const char *buf, size_t len);
static int on_headers_complete (http_parser *parser); static int on_headers_complete (http_parser *parser);

Loading…
Cancel
Save