From e2b79024699c3f1171ef2f312067b0f05348e961 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Sun, 4 Oct 2009 12:17:50 +0200 Subject: [PATCH] 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. --- doc/api.txt | 21 +++++---------------- lib/http.js | 23 ++++++++++++++++++++--- src/http.cc | 33 +++++++++++++++++++++++++++++++++ src/http.h | 6 ++++++ 4 files changed, 64 insertions(+), 19 deletions(-) diff --git a/doc/api.txt b/doc/api.txt index 07708ef0da..d37fec565e 100644 --- a/doc/api.txt +++ b/doc/api.txt @@ -665,7 +665,7 @@ The request method as a string. Read only. Example: +request.uri+ :: 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 @@ -676,23 +676,12 @@ Accept: text/plain\r\n Then +request.uri+ will be + ---------------------------------------- -{ path: "/status", - file: "status", - directory: "/", - params: { "name" : "ryan" } +{ full: "/status?name=ryan", + path: "/status", + queryString: "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+ :: diff --git a/lib/http.js b/lib/http.js index b30ebd6987..8282794dd5 100644 --- a/lib/http.js +++ b/lib/http.js @@ -125,7 +125,13 @@ function IncomingMessage (connection) { this.headers = {}; // request (server) only - this.uri = ""; + this.uri = { + full: "", + queryString: "", + fragment: "", + path: "" + }; + this.method = null; // response (client) only @@ -338,7 +344,19 @@ function createIncomingMessageStream (connection, incoming_listener) { // Only servers will get URI events. 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) { @@ -372,7 +390,6 @@ function createIncomingMessageStream (connection, incoming_listener) { if (info.method) { // server only incoming.method = info.method; - incoming.uri = exports.parseUri(incoming.uri); // TODO parse the URI lazily? } else { // client only incoming.statusCode = info.statusCode; diff --git a/src/http.cc b/src/http.cc index 1d2d2b480e..841ccbd6f4 100644 --- a/src/http.cc +++ b/src/http.cc @@ -95,6 +95,39 @@ HTTPConnection::on_uri (http_parser *parser, const char *buf, size_t len) return 0; } +int +HTTPConnection::on_query_string (http_parser *parser, const char *buf, size_t len) +{ + HandleScope scope; + HTTPConnection *connection = static_cast(parser->data); + assert(connection->attached_); + Local 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(parser->data); + assert(connection->attached_); + Local 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(parser->data); + assert(connection->attached_); + Local argv[1] = { String::New(buf, len) }; + connection->Emit("fragment", 1, argv); + return 0; +} + int HTTPConnection::on_header_field (http_parser *parser, const char *buf, size_t len) { diff --git a/src/http.h b/src/http.h index fa3f65de28..d464832d59 100644 --- a/src/http.h +++ b/src/http.h @@ -24,6 +24,9 @@ protected: http_parser_init (&parser_, type); parser_.on_message_begin = on_message_begin; 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_value = on_header_value; parser_.on_headers_complete = on_headers_complete; @@ -36,6 +39,9 @@ protected: static int on_message_begin (http_parser *parser); 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_value (http_parser *parser, const char *buf, size_t len); static int on_headers_complete (http_parser *parser);