mirror of
https://github.com/nodejs/node.git
synced 2024-11-29 07:00:59 +01:00
extract headers, status_code, path, http version from http messages.
still a work in progress.
This commit is contained in:
parent
5a071ad72f
commit
be6b3acf0e
176
src/http.cc
176
src/http.cc
@ -5,16 +5,73 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define ON_MESSAGE_SYMBOL String::NewSymbol("onMessage")
|
||||
#define MESSAGE_HANDLER_SYMBOL String::NewSymbol("messageHandler")
|
||||
#define ON_HEADERS_COMPLETE_SYMBOL String::NewSymbol("onHeadersComplete")
|
||||
|
||||
#define PATH_SYMBOL String::NewSymbol("path")
|
||||
#define STATUS_CODE_SYMBOL String::NewSymbol("status_code")
|
||||
#define HTTP_VERSION_SYMBOL String::NewSymbol("http_version")
|
||||
|
||||
using namespace v8;
|
||||
using namespace node;
|
||||
using namespace std;
|
||||
|
||||
|
||||
// Helper Functions
|
||||
|
||||
static Persistent<Function> _fill_field;
|
||||
static Persistent<Function> _append_header_field;
|
||||
static Persistent<Function> _append_header_value;
|
||||
|
||||
#define CATCH_NATIVE_HTTP_FUNCTION(variable, jsname) \
|
||||
do { \
|
||||
if (variable.IsEmpty()) { \
|
||||
Local<Object> __g = Context::GetCurrent()->Global(); \
|
||||
Local<Value> __node_v = __g->Get(String::NewSymbol("node")); \
|
||||
Local<Object> __node = __node_v->ToObject(); \
|
||||
Local<Value> __http_v = __node->Get(String::NewSymbol("http")); \
|
||||
Local<Object> __http = __http_v->ToObject(); \
|
||||
Local<Value> __value = __http->Get(String::NewSymbol(jsname)); \
|
||||
Handle<Function> __function_handle = Handle<Function>::Cast(__value); \
|
||||
variable = Persistent<Function>::New(__function_handle); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
void
|
||||
HTTPClient::Initialize (Handle<Object> target)
|
||||
fillField (Handle<Value> message, Handle<Value> field, Handle<Value> value)
|
||||
{
|
||||
HandleScope scope;
|
||||
CATCH_NATIVE_HTTP_FUNCTION(_fill_field, "fillField");
|
||||
Handle<Value> argv[] = { message, field, value };
|
||||
_fill_field->Call(message->ToObject(), 3, argv);
|
||||
}
|
||||
|
||||
void
|
||||
appendHeaderField (Handle<Value> message, Handle<Value> d)
|
||||
{
|
||||
HandleScope scope;
|
||||
CATCH_NATIVE_HTTP_FUNCTION(_append_header_field, "appendHeaderField");
|
||||
Handle<Value> argv[] = { message, d };
|
||||
_append_header_field->Call(message->ToObject(), 2, argv);
|
||||
}
|
||||
|
||||
void
|
||||
appendHeaderValue (Handle<Value> message, Handle<Value> d)
|
||||
{
|
||||
HandleScope scope;
|
||||
CATCH_NATIVE_HTTP_FUNCTION(_append_header_value, "appendHeaderValue");
|
||||
Handle<Value> argv[] = { message, d };
|
||||
_append_header_value->Call(message->ToObject(), 2, argv);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HTTPConnection::Initialize (Handle<Object> target)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
Local<FunctionTemplate> t = FunctionTemplate::New(HTTPClient::v8New);
|
||||
Local<FunctionTemplate> t = FunctionTemplate::New(HTTPConnection::v8New);
|
||||
t->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
target->Set(String::NewSymbol("HTTPClient"), t->GetFunction());
|
||||
|
||||
@ -25,7 +82,7 @@ HTTPClient::Initialize (Handle<Object> target)
|
||||
}
|
||||
|
||||
Handle<Value>
|
||||
HTTPClient::v8New (const Arguments& args)
|
||||
HTTPConnection::v8New (const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
@ -44,18 +101,121 @@ HTTPClient::v8New (const Arguments& args)
|
||||
|
||||
Local<Object> protocol_instance = protocol->NewInstance(argc, argv);
|
||||
|
||||
new HTTPClient(args.This(), protocol_instance);
|
||||
// changeme the type should come from javascript
|
||||
new HTTPConnection(args.This(), protocol_instance, HTTP_RESPONSE);
|
||||
|
||||
return args.This();
|
||||
}
|
||||
|
||||
void
|
||||
HTTPClient::OnReceive (const void *buf, size_t len)
|
||||
HTTPConnection::OnReceive (const void *buf, size_t len)
|
||||
{
|
||||
printf("http client got data!\n");
|
||||
http_parser_execute(&parser_, static_cast<const char*>(buf), len);
|
||||
|
||||
if (http_parser_has_error(&parser_)) {
|
||||
// do something.
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
HTTPClient::HTTPClient (Handle<Object> handle, Handle<Object> protocol)
|
||||
int
|
||||
HTTPConnection::on_message_begin (http_parser *parser)
|
||||
{
|
||||
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
|
||||
HandleScope scope;
|
||||
|
||||
Local<Object> protocol = connection->GetProtocol();
|
||||
Local<Value> on_message_v = protocol->Get(ON_MESSAGE_SYMBOL);
|
||||
if (!on_message_v->IsFunction()) return -1;
|
||||
Handle<Function> on_message = Handle<Function>::Cast(on_message_v);
|
||||
Local<Object> message_handler = on_message->NewInstance();
|
||||
connection->handle_->SetHiddenValue(MESSAGE_HANDLER_SYMBOL, message_handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
HTTPConnection::on_path (http_parser *parser, const char *buf, size_t len)
|
||||
{
|
||||
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
Local<Value> message_handler_v =
|
||||
connection->handle_->GetHiddenValue(MESSAGE_HANDLER_SYMBOL);
|
||||
fillField(message_handler_v, PATH_SYMBOL, String::New(buf, len));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
HTTPConnection::on_header_field (http_parser *parser, const char *buf, size_t len)
|
||||
{
|
||||
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
|
||||
HandleScope scope;
|
||||
Local<Value> message_handler_v =
|
||||
connection->handle_->GetHiddenValue(MESSAGE_HANDLER_SYMBOL);
|
||||
appendHeaderField(message_handler_v, String::New(buf, len));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
HTTPConnection::on_header_value (http_parser *parser, const char *buf, size_t len)
|
||||
{
|
||||
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
|
||||
HandleScope scope;
|
||||
Local<Value> message_handler_v =
|
||||
connection->handle_->GetHiddenValue(MESSAGE_HANDLER_SYMBOL);
|
||||
appendHeaderValue(message_handler_v, String::New(buf, len));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
HTTPConnection::on_headers_complete (http_parser *parser)
|
||||
{
|
||||
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
|
||||
|
||||
Local<Value> message_handler_v =
|
||||
connection->handle_->GetHiddenValue(MESSAGE_HANDLER_SYMBOL);
|
||||
Local<Object> message_handler = message_handler_v->ToObject();
|
||||
|
||||
// STATUS
|
||||
message_handler->Set(STATUS_CODE_SYMBOL,
|
||||
Integer::New(connection->parser_.status_code));
|
||||
|
||||
// VERSION
|
||||
char version[10];
|
||||
snprintf(version, 10, "%d.%d", connection->parser_.version_major, connection->parser_.version_minor);
|
||||
message_handler->Set(HTTP_VERSION_SYMBOL, String::New(version));
|
||||
|
||||
|
||||
|
||||
|
||||
Local<Value> on_headers_complete_v = message_handler->Get(ON_HEADERS_COMPLETE_SYMBOL);
|
||||
if (on_headers_complete_v->IsFunction() == false) return 0;
|
||||
|
||||
Handle<Function> on_headers_complete = Handle<Function>::Cast(on_headers_complete_v);
|
||||
|
||||
|
||||
on_headers_complete->Call(message_handler, 0, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HTTPConnection::HTTPConnection (Handle<Object> handle, Handle<Object> protocol, enum http_parser_type type)
|
||||
: Connection(handle, protocol)
|
||||
{
|
||||
}
|
||||
http_parser_init (&parser_, type);
|
||||
parser_.on_message_begin = on_message_begin;
|
||||
parser_.on_path = on_path;
|
||||
parser_.on_query_string = NULL;
|
||||
parser_.on_uri = NULL;
|
||||
parser_.on_fragment = NULL;
|
||||
parser_.on_header_field = on_header_field;
|
||||
parser_.on_header_value = on_header_value;
|
||||
parser_.on_headers_complete = on_headers_complete;
|
||||
parser_.on_body = NULL;
|
||||
parser_.on_message_complete = NULL;
|
||||
parser_.data = this;
|
||||
}
|
||||
|
||||
|
15
src/http.h
15
src/http.h
@ -3,19 +3,30 @@
|
||||
|
||||
#include <v8.h>
|
||||
#include "net.h"
|
||||
#include <http_parser.h>
|
||||
|
||||
namespace node {
|
||||
|
||||
class HTTPClient : public node::Connection {
|
||||
class HTTPConnection : public Connection {
|
||||
public:
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
|
||||
HTTPClient (v8::Handle<v8::Object> handle, v8::Handle<v8::Object> protocol);
|
||||
HTTPConnection (v8::Handle<v8::Object> handle,
|
||||
v8::Handle<v8::Object> protocol,
|
||||
enum http_parser_type type);
|
||||
|
||||
static v8::Handle<v8::Value> v8New (const v8::Arguments& args);
|
||||
protected:
|
||||
void OnReceive (const void *buf, size_t len);
|
||||
|
||||
static int on_message_begin (http_parser *parser);
|
||||
static int on_path (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);
|
||||
|
||||
|
||||
http_parser parser_;
|
||||
};
|
||||
|
||||
} // namespace node
|
||||
|
25
src/http.js
Normal file
25
src/http.js
Normal file
@ -0,0 +1,25 @@
|
||||
node.http = {
|
||||
fillField : function (msg, field, data) {
|
||||
msg[field] = (msg[field] || "") + data;
|
||||
},
|
||||
|
||||
appendHeaderField : function (msg, data) {
|
||||
if (msg.hasOwnProperty("headers")) {
|
||||
var last_pair = msg.headers[msg.headers.length-1];
|
||||
if (last_pair.length == 1)
|
||||
last_pair[0] += data;
|
||||
else
|
||||
msg.headers.push([data]);
|
||||
} else {
|
||||
msg.headers = [[data]];
|
||||
}
|
||||
},
|
||||
|
||||
appendHeaderValue : function (msg, data) {
|
||||
var last_pair = msg.headers[msg.headers.length-1];
|
||||
if (last_pair.length == 1)
|
||||
last_pair[1] = data;
|
||||
else
|
||||
last_pair[1] += data;
|
||||
}
|
||||
};
|
@ -178,4 +178,3 @@ clearInterval = clearTimeout;
|
||||
|
||||
loadScript(ARGV[1], this);
|
||||
})();
|
||||
|
||||
|
@ -56,9 +56,6 @@ ObjectWrap::MakeWeak (Persistent<Value> _, void *data)
|
||||
delete w;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Extracts a C string from a V8 Utf8Value.
|
||||
const char*
|
||||
ToCString(const v8::String::Utf8Value& value)
|
||||
@ -252,11 +249,14 @@ main (int argc, char *argv[])
|
||||
Connection::Initialize(g);
|
||||
node::Init_timer(g);
|
||||
node::Init_file(g);
|
||||
HTTPClient::Initialize(g);
|
||||
HTTPConnection::Initialize(g);
|
||||
|
||||
// NATIVE JAVASCRIPT MODULES
|
||||
TryCatch try_catch;
|
||||
|
||||
ExecuteString(String::New(native_http), String::New("http.js"));
|
||||
if (try_catch.HasCaught()) goto native_js_error;
|
||||
|
||||
ExecuteString(String::New(native_file), String::New("file.js"));
|
||||
if (try_catch.HasCaught()) goto native_js_error;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user