use c++ instead of c++0x to compatible with old compiler

This commit is contained in:
jiangfriend@gmail.com 2012-02-14 21:10:45 +08:00
parent f8f934a119
commit 314d43203f
11 changed files with 454 additions and 106 deletions

View file

@ -1,36 +1,88 @@
Node Curl Wrap
Use select curl multi
node-curl
=========
node cURL wrapper, support all options and infos.
Quick Start
===========
-----------
* quick start
curl = require('node-curl');
curl('www.google.com', function(err, res) {
console.info(res.status);
console.info('-----');
console.info(res.body);
console.info('-----');
console.info(res.info('SIZE_DOWNLOAD'));
res.close();
});
* with options
curl = require('node-curl')
curl('www.google.com', {VERBOSE: 1}, function(err, res) {
console.info(res.status)
console.info('-----')
console.info(res.body)
console.info('-----')
console.info(res.info('SIZE_DOWNLOAD'))
curl('www.google.com', {VERBOSE: 1, RAW: 1}, function(err, res) {
console.info(res);
res.close();
});
Usage
=====
-----
* curl
Function: curl
curl(url, [options = {}], callback)
callback includes 2 parameters (error, result)
Curl Options:
options is on the list at http://curl.haxx.se/libcurl/c/curl_easy_setopt.html without CURLOPT_
* result in callback
members:
status - Http Response code
body - Http body
methods:
info(name) - Get information of result, see 'info' section
Options
-------
* Any Curl Easy Options
eg: CURLOPT_VERBOSE will be VERBOSE, CURLOPT_HEADER will be HEADER
Object: result
body
status
info
Full list at http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
* node-curl Extra Options
RAW - Returns Buffer instead of String in result.body
* About slist parameters
node-curl support slist which map to Javascript Array
eg:
HTTP_HEADER: ['FOO', 'BAR']
HTTP_HEADER: 'FOO'
any non-array parameter will convert to [ parameter.toString() ]
Infos
-----
* Any Curl Info options
Curl Infos:
infos is on the list at http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html without CURLINFO_
eg: CURLINFO_EFFECTIVE_URL will be EFFETCTIVE_URL
full list at http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html
* About slist
slist will be returns in Array
eg: CURLINFO_COOKIELIST
Hints
-----
close the result to release resource of curl immediately.
or the resource will not release until gc performed.

30
examples/pressure.js Normal file
View file

@ -0,0 +1,30 @@
// Generated by ToffeeScript 1.1.4-4
(function() {
var assert, curl, i, j, next, once, _i;
curl = require('../index');
assert = require('assert');
j = 0;
(next = function() {
console.info("curl instances: ", curl.get_count());
return setTimeout(next, 1000);
})();
for (i = _i = 1; _i <= 100; i = ++_i) {
(once = function() {
var _this = this;
return curl('localhost/test.html', function(_$$_err, _$$_res) {
var err, res;
err = _$$_err;
res = _$$_res;
assert.equal(res.body.length, 1468);
if (++j % 100 === 0) console.info(j);
if (j < 20000) return once();
});
})();
}
}).call(this);

16
examples/pressure.toffee Normal file
View file

@ -0,0 +1,16 @@
curl = require '../index'
assert = require 'assert'
j = 0;
do next = ->
console.info "curl instances: ", curl.get_count()
setTimeout next, 1000
for i in [1..100]
do once = ->
err, res = curl! 'localhost/test.html'
assert.equal res.body.length, 1468
if ++j % 100 == 0
console.info j
if j < 20000
once()
# res.close()

View file

@ -1,19 +1,27 @@
curl = require('../index');
url = 'www.yahoo.com';
curl(url, function(err, res) {
url = 'www.nodejs.org';
options = {CONNECTTIMEOUT: 2, VERBOSE: 1};
curl(url, options, function(err, res) {
console.info("\x1b[33meffetcive url: " + res.info('EFFECTIVE_URL') + "\x1b[0m");
console.info("body length: " + res.body.length);
console.info('-----');
console.info("status: " + res.status);
console.info('-----');
console.info("size download: " + res.info('SIZE_DOWNLOAD'));
console.info("\033[33meffetcive url: " + res.info('EFFECTIVE_URL') + "\033[0m");
res.close();
});
curl(url, function(err, res) {
url = 'www.yahoo.com'
curl(url, options, function(err, res) {
console.info("\x1b[33meffetcive url: " + res.info('EFFECTIVE_URL') + "\x1b[0m");
console.info("body length: " + res.body.length);
res.close();
});
curl('www.google.com', {VERBOSE: 1, RAW: 1}, function(err, res) {
console.info(res);
res.close();
});
/*
console.info('-----');
console.info("status: " + res.status);
console.info('-----');
console.info("size download: " + res.info('SIZE_DOWNLOAD'));
console.info("\033[33meffetcive url: " + res.info('EFFECTIVE_URL') + "\033[0m");
});
*/

40
examples/test.js Normal file
View file

@ -0,0 +1,40 @@
// Generated by ToffeeScript 1.1.4-4
(function() {
var curl, fs, p, url, util,
_this = this;
curl = require('../index');
fs = require('fs');
util = require('util');
p = console.info;
url = 'www.google.com';
curl(url, {
HTTPHEADER: 'BAR',
VERBOSE: 1,
COOKIEFILE: 'node-curl-cookie.txt'
}, function(_$$_err, _$$_res) {
var err, res;
err = _$$_err;
res = _$$_res;
p("\x1b[33m" + util.inspect(res.info('COOKIELIST')) + "\x1b[0m");
url = 'www.yahoo.com';
return curl(url, {
HTTPHEADER: ['foo', 'bar'],
VERBOSE: 1,
COOKIEFILE: 'node-curl-cookie.txt',
RAW: 1
}, function(_$$_err, _$$_res) {
err = _$$_err;
res = _$$_res;
p("\x1b[33m" + util.inspect(res.info('COOKIELIST')) + "\x1b[0m");
p(res.body);
return fs.unlink('node-curl-cookie.txt');
});
});
}).call(this);

22
examples/test.toffee Normal file
View file

@ -0,0 +1,22 @@
curl = require '../index'
fs = require 'fs'
util = require 'util'
p = console.info
url = 'www.google.com'
err, res = curl! url,
HTTPHEADER: 'BAR'
VERBOSE: 1
COOKIEFILE: 'node-curl-cookie.txt'
p "\x1b[33m" + util.inspect(res.info('COOKIELIST')) + "\x1b[0m"
url = 'www.yahoo.com'
err, res = curl! url,
HTTPHEADER: ['foo', 'bar']
VERBOSE: 1
COOKIEFILE: 'node-curl-cookie.txt'
RAW: 1
p "\x1b[33m" + util.inspect(res.info('COOKIELIST')) + "\x1b[0m"
p res.body
fs.unlink 'node-curl-cookie.txt'

View file

@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.1.4-3
// Generated by ToffeeScript 1.1.4-4
(function() {
var Curl, curl, curl_id,
var Curl, curl, curl_id, curls,
__slice = [].slice,
__hasProp = {}.hasOwnProperty;
@ -10,10 +10,18 @@
Curl = require(__dirname + '/../build/default/node-curl').Curl;
}
Curl.prototype.setopt_user_ = function(option_id, value) {
return this.options[option_id] = value;
};
Curl.prototype.setopt = function(ooption, value) {
var option, option_id;
option = ooption.toUpperCase();
if ((option_id = Curl.integer_options[option]) != null) {
if ((option_id = Curl.user_options[option]) != null) {
return this.setopt_user_(option_id, value);
} else if ((option_id = Curl.slist_options[option]) != null) {
return this.setopt_slist_(option_id, value);
} else if ((option_id = Curl.integer_options[option]) != null) {
return this.setopt_int_(option_id, value >> 0);
} else if ((option_id = Curl.string_options[option]) != null) {
return this.setopt_str_(option_id, value.toString());
@ -25,14 +33,16 @@
Curl.prototype.getinfo = function(oinfo) {
var info, info_id;
info = oinfo.toUpperCase();
if ((info_id = Curl.integer_infos[info]) != null) {
if ((info_id = Curl.slist_infos[info]) != null) {
return this.getinfo_slist_(info_id);
} else if ((info_id = Curl.integer_infos[info]) != null) {
return this.getinfo_int_(info_id);
} else if ((info_id = Curl.string_infos[info]) != null) {
return this.getinfo_str_(info_id);
} else if ((info_id = Curl.double_infos[info]) != null) {
return this.getinfo_double_(info_id);
} else {
throw new Error("unsupproted info " + oinfo);
throw new Error("unsupported info " + oinfo);
}
};
@ -41,6 +51,10 @@
return Curl.process();
};
Curl.user_options = {
RAW: 'RAW'
};
Curl.process = function() {
var once;
if (Curl.in_process) return;
@ -58,63 +72,84 @@
curl_id = 0;
curls = {};
curl = function() {
var args, c, cb, chunks, k, length, options, res, url, v;
var args, c, cb, k, length, options, url, v;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
cb = args.pop();
url = args[0], options = args[1];
if (options == null) options = {};
c = new Curl();
c.options = {};
c.id = ++curl_id;
curls[c.id] = c;
c.setopt('FOLLOWLOCATION', 1);
c.setopt('ACCEPT_ENCODING', 'gzip');
chunks = [];
c.chunks = [];
length = 0;
res = {};
for (k in options) {
if (!__hasProp.call(options, k)) continue;
v = options[k];
c.setopt(k, v);
}
c.on_write = function(chunk) {
chunks.push(chunk);
length += chunk.length;
return console.info("on_write " + c.id + " " + chunk.length);
c.chunks.push(chunk);
return length += chunk.length;
};
c.on_end = function() {
var chunk, data, i, position, st, _i, _len;
var chunk, data, position, res, _i, _len, _ref,
_this = this;
data = new Buffer(length);
position = 0;
for (_i = 0, _len = chunks.length; _i < _len; _i++) {
chunk = chunks[_i];
_ref = c.chunks;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
chunk = _ref[_i];
chunk.copy(data, position);
position += chunk.length;
}
st = Date.now();
i = 0;
while (Date.now() - st < 500) {
++i;
}
c.chunks = [];
res = {};
res.curl_ = c;
delete curls[c.id];
if (c.options.RAW) {
res.body = data;
} else {
res.body = data.toString();
}
res.status = res.code = c.getinfo('RESPONSE_CODE');
res.info = function(info) {
return c.getinfo(info);
if (this.curl_ == null) throw new Error('curl is closed');
return this.curl_.getinfo(info);
};
console.info("id: " + c.id);
res.close = function() {
if (this.curl_ != null) this.curl_.close();
this.curl_ = null;
return this.body = null;
};
return process.nextTick(function() {
return cb(null, res);
});
};
c.on_error = function(err) {
var _this = this;
curls[c.id].close();
delete curls[c.id];
return process.nextTick(function() {
return cb(err, null);
});
};
c.setopt('URL', url);
return c.perform();
c.perform();
return c;
};
curl.Curl = Curl;
curl.get_count = function() {
return Curl.get_count();
};
module.exports = curl;
}).call(this);

View file

@ -3,9 +3,19 @@ try
catch e
{Curl} = require __dirname + '/../build/default/node-curl'
Curl::setopt_user_ = (option_id, value) ->
@options[option_id] = value
Curl::setopt = (ooption, value) ->
option = ooption.toUpperCase()
if (option_id = Curl.integer_options[option])?
# slist must be at the top of condition
# the option exists in string_options too
if (option_id = Curl.user_options[option])?
@setopt_user_ option_id, value
else if (option_id = Curl.slist_options[option])?
@setopt_slist_ option_id, value
else if (option_id = Curl.integer_options[option])?
@setopt_int_ option_id, value >> 0
else if (option_id = Curl.string_options[option])?
@setopt_str_ option_id, value.toString()
@ -14,19 +24,24 @@ Curl::setopt = (ooption, value) ->
Curl::getinfo = (oinfo) ->
info = oinfo.toUpperCase()
if (info_id = Curl.integer_infos[info])?
if (info_id = Curl.slist_infos[info])?
@getinfo_slist_(info_id)
else if (info_id = Curl.integer_infos[info])?
@getinfo_int_(info_id)
else if (info_id = Curl.string_infos[info])?
@getinfo_str_(info_id)
else if (info_id = Curl.double_infos[info])?
@getinfo_double_(info_id)
else
throw new Error("unsupproted info #{oinfo}")
throw new Error("unsupported info #{oinfo}")
Curl::perform = ->
@perform_()
Curl.process()
Curl.user_options =
RAW: 'RAW'
Curl.process = ->
if Curl.in_process
return
@ -40,56 +55,75 @@ Curl.process = ->
# url, [options], cb
curl_id = 0
curls = {}
curl = (args...) ->
cb = args.pop()
[url, options] = args
options ?= {}
c = new Curl()
c.options = {}
c.id = ++curl_id
# after the scope c will not valid any more, so add to curls to keep c alive
curls[c.id] = c
c.setopt 'FOLLOWLOCATION', 1
c.setopt 'ACCEPT_ENCODING', 'gzip'
chunks = []
c.chunks = []
length = 0
res = {}
for own k, v of options
c.setopt k, v
c.on_write = (chunk) ->
chunks.push chunk
c.chunks.push chunk
length += chunk.length
console.info "on_write #{c.id} #{chunk.length}"
c.on_end = ->
data = new Buffer(length)
position = 0
for chunk in chunks
for chunk in c.chunks
chunk.copy data, position
position += chunk.length
# Strange Issue
# use data.toString() will cause parallel http request terminated? eg yahoo.com
st = Date.now()
i = 0
while Date.now() - st < 500
++i
c.chunks = []
res = {}
# now the c is in res.curl, delete curl in curls
# if res destruct, curl will be destruct after gc
res.curl_ = c
delete curls[c.id]
res.body = data #.toString()
if c.options.RAW
res.body = data
else
res.body = data.toString() #.toString()
res.status = res.code = c.getinfo('RESPONSE_CODE')
res.info = (info)->
c.getinfo(info)
# 当curl返回过快且cb循环调用回导致堆栈溢出
# process.nextTick!
console.info "id: #{c.id}"
unless @curl_?
throw new Error('curl is closed')
@curl_.getinfo(info)
res.close = ->
@curl_.close() if @curl_?
@curl_ = null
@body = null
# if curl returns to fast, avoid cb recursive call
process.nextTick!
cb null, res
c.on_error = (err)->
curls[c.id].close()
delete curls[c.id]
process.nextTick!
cb err, null
c.setopt('URL', url)
c.perform()
c
curl.Curl = Curl
curl.get_count = ->
Curl.get_count()
module.exports = curl

View file

@ -1,14 +1,14 @@
{
"name": "node-curl",
"version": "0.1.0",
"description": "node wrapper for multi curl",
"author" : "Jiang Miao <jiangfriend@gmail.com>",
"description": "node wrapper for multi curl, full implemented.",
"keywords" : ["node-curl", "curl", "multi-curl", "mcurl"],
"homepage": "http://github.com/jiangmiao/node-curl",
"repository" : {
"type" : "git",
"url" : "git://github.com/jiangmiao/node-curl.git"
},
"author" : "Jiang Miao <jiangfriend@gmail.com>",
"main" : "./lib",
"scripts" : {
"install" : "node-waf configure build || true"

View file

@ -8,6 +8,7 @@
#include <node_buffer.h>
#include <curl/curl.h>
#include <map>
#include <vector>
#define NODE_CURL_OPTION_NX(name, value) {#name, value}
#define NODE_CURL_OPTION(name) NODE_CURL_OPTION_NX(name , CURLOPT_##name)
@ -26,11 +27,17 @@ class NodeCurl
static int running_handles;
static bool is_ref;
static std::map< CURL*, NodeCurl* > curls;
static int count;
CURL * curl;
v8::Persistent<v8::Object> handle;
bool in_curlm;
std::vector<curl_slist*> slists;
NodeCurl(v8::Handle<v8::Object> object)
: in_curlm(false)
{
++count;
v8::V8::AdjustAmountOfExternalAllocatedMemory(2*4096);
object->SetPointerInInternalField(0, this);
handle = v8::Persistent<v8::Object>::New(object);
handle.MakeWeak(this, destructor);
@ -39,6 +46,7 @@ class NodeCurl
if (!curl)
{
raise("curl_easy_init failed");
return;
}
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_function);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
@ -47,18 +55,31 @@ class NodeCurl
~NodeCurl()
{
--count;
v8::V8::AdjustAmountOfExternalAllocatedMemory(-2*4096);
if (curl)
{
if (in_curlm)
curl_multi_remove_handle(curlm, curl);
curl_easy_cleanup(curl);
curls.erase(curl);
}
for (std::vector<curl_slist*>::iterator i = slists.begin(), e = slists.end(); i != e; ++i)
{
curl_slist * slist = *i;
if (slist)
{
curl_slist_free_all(slist);
}
}
}
static void destructor(v8::Persistent<v8::Value> object, void *data)
static void destructor(v8::Persistent<v8::Value> value, void *data)
{
NodeCurl * curl = (NodeCurl*)object->ToObject()->GetPointerFromInternalField(0);
delete curl;
v8::Handle<v8::Object> object = value->ToObject();
NodeCurl * curl = (NodeCurl*)object->GetPointerFromInternalField(0);
curl->close();
}
void close()
@ -68,6 +89,15 @@ class NodeCurl
delete this;
}
static v8::Handle<v8::Value> close(const v8::Arguments & args)
{
NodeCurl * node_curl = unwrap(args.This());
if (node_curl)
node_curl->close();
return args.This();
}
static NodeCurl * unwrap(v8::Handle<v8::Object> value)
{
return (NodeCurl*)value->GetPointerFromInternalField(0);
@ -82,12 +112,11 @@ class NodeCurl
size_t on_write(char *data, size_t n)
{
v8::HandleScope scope;
static auto SYM_ON_WRITE = v8::Persistent<v8::String>::New(v8::String::NewSymbol("on_write"));
auto cb = handle->Get(SYM_ON_WRITE);
static v8::Persistent<v8::String> SYM_ON_WRITE = v8::Persistent<v8::String>::New(v8::String::NewSymbol("on_write"));
v8::Handle<v8::Value> cb = handle->Get(SYM_ON_WRITE);
if (cb->IsFunction())
{
auto buffer = node::Buffer::New(data, n);
node::Buffer * buffer = node::Buffer::New(data, n);
v8::Handle<v8::Value> argv[] = { buffer->handle_ };
cb->ToObject()->CallAsFunction(handle, 1, argv);
}
@ -96,8 +125,8 @@ class NodeCurl
void on_end(CURLMsg *msg)
{
static auto SYM_ON_END = v8::Persistent<v8::String>::New(v8::String::NewSymbol("on_end"));
auto cb = handle->Get(SYM_ON_END);
static v8::Persistent<v8::String> SYM_ON_END = v8::Persistent<v8::String>::New(v8::String::NewSymbol("on_end"));
v8::Handle<v8::Value> cb = handle->Get(SYM_ON_END);
if (cb->IsFunction())
{
v8::Handle<v8::Value> argv[] = {};
@ -107,8 +136,8 @@ class NodeCurl
void on_error(CURLMsg *msg)
{
static auto SYM_ON_ERROR = v8::Persistent<v8::String>::New(v8::String::NewSymbol("on_error"));
auto cb = handle->Get(SYM_ON_ERROR);
static v8::Persistent<v8::String> SYM_ON_ERROR = v8::Persistent<v8::String>::New(v8::String::NewSymbol("on_error"));
v8::Handle<v8::Value> cb = handle->Get(SYM_ON_ERROR);
if (cb->IsFunction())
{
v8::Handle<v8::Value> argv[] = {v8::Exception::Error(v8::String::New(curl_easy_strerror(msg->data.result)))};
@ -117,10 +146,10 @@ class NodeCurl
}
// curl_easy_getinfo
template<typename T, typename S>
template<typename CType, typename JsClass>
static v8::Handle<v8::Value> getinfo(const v8::Arguments &args)
{
T result;
CType result;
NodeCurl * node_curl = unwrap(args.This());
CURLINFO info = (CURLINFO)args[0]->Int32Value();
CURLcode code = curl_easy_getinfo(node_curl->curl, info, &result);
@ -128,7 +157,7 @@ class NodeCurl
{
return raise("curl_easy_getinfo failed", curl_easy_strerror(code));
}
return S::New(result);
return JsClass::New(result);
}
static v8::Handle<v8::Value> getinfo_int(const v8::Arguments & args)
@ -146,6 +175,30 @@ class NodeCurl
return getinfo<double, v8::Number>(args);
}
static v8::Handle<v8::Value> getinfo_slist(const v8::Arguments & args)
{
curl_slist * slist, * cur;
NodeCurl* node_curl = unwrap(args.This());
CURLINFO info = (CURLINFO)args[0]->Int32Value();
CURLcode code = curl_easy_getinfo(node_curl->curl, info, &slist);
if (code != CURLE_OK)
{
return raise("curl_easy_getinfo failed", curl_easy_strerror(code));
}
v8::Handle<v8::Array> array = v8::Array::New();
if (slist)
{
cur = slist;
while (cur)
{
array->Set(array->Length(), v8::String::New(slist->data));
cur = cur->next;
}
curl_slist_free_all(slist);
}
return array;
}
// curl_easy_setopt
template<typename T>
v8::Handle<v8::Value> setopt(v8::Handle<v8::Value> option, T value)
@ -169,6 +222,32 @@ class NodeCurl
return unwrap(args.This())->setopt(args[0], *v8::String::Utf8Value(args[1]) );
}
static v8::Handle<v8::Value> setopt_slist(const v8::Arguments & args)
{
NodeCurl * node_curl = unwrap(args.This());
curl_slist * slist = value_to_slist(args[1]);
node_curl->slists.push_back(slist);
return node_curl->setopt(args[0], slist);
}
static curl_slist * value_to_slist(v8::Handle<v8::Value> value)
{
curl_slist * slist = NULL;
if (!value->IsArray())
{
slist = curl_slist_append(slist, *v8::String::Utf8Value(value));
}
else
{
v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
for (uint32_t i=0, len = array->Length(); i<len; ++i)
{
slist = curl_slist_append(slist, *v8::String::Utf8Value(array->Get(i)));
}
}
return slist;
}
static v8::Handle<v8::Value> raise(const char *data, const char *reason = NULL)
{
@ -185,10 +264,10 @@ class NodeCurl
template<typename T>
static void export_curl_options(T t, const char *group_name, CurlOption *options, int len)
{
auto node_options = v8::Object::New();
v8::Handle<v8::Object> node_options = v8::Object::New();
for (int i=0; i<len; ++i)
{
const auto & option = options[i];
const CurlOption & option = options[i];
node_options->Set(
v8::String::NewSymbol(option.name),
v8::Integer::New(option.value)
@ -223,12 +302,10 @@ class NodeCurl
{
return raise("curl_multi_fdset failed", curl_multi_strerror(code));
}
printf("maxfd returns %d\n", max_fd);
if (max_fd > 0)
{
timeval tv = {0};
int n = select(max_fd+1, &read_fds, &write_fds, &error_fds, &tv);
printf("selecting returns %d\n", n);
if (n == 0)
{
return v8::Integer::New(running_handles);
@ -249,21 +326,20 @@ class NodeCurl
CURLMsg * msg = NULL;
while ( (msg = curl_multi_info_read(curlm, &msgs)) )
{
printf("msgs: %d, running_handles: %d\n", msgs, running_handles);
if (msg->msg == CURLMSG_DONE)
{
auto curl = curls[msg->easy_handle];
NodeCurl * curl = curls[msg->easy_handle];
if (msg->data.result == CURLE_OK)
curl->on_end(msg);
else
curl->on_error(msg);
code = curl_multi_remove_handle(curlm, msg->easy_handle);
curl->in_curlm = false;
if (code != CURLM_OK)
{
return raise("curl_multi_remove_handle failed", curl_multi_strerror(code));
}
}
puts("done.");
}
}
return v8::Integer::New(running_handles);
@ -274,6 +350,7 @@ class NodeCurl
{
NodeCurl *curl = unwrap(args.This());
CURLMcode code = curl_multi_add_handle(curlm, curl->curl);
curl->in_curlm = true;
if (code != CURLM_OK)
{
return raise("curl_multi_add_handle failed", curl_multi_strerror(code));
@ -282,6 +359,11 @@ class NodeCurl
return args.This();
}
static v8::Handle<v8::Value> get_count(const v8::Arguments & args )
{
return v8::Integer::New(count);
}
public:
static v8::Handle<v8::Value> Initialize(v8::Handle<v8::Object> target)
{
@ -299,19 +381,24 @@ class NodeCurl
}
// Initialize node-curl
auto t = v8::FunctionTemplate::New(New);
v8::Handle<v8::FunctionTemplate> t = v8::FunctionTemplate::New(New);
t->InstanceTemplate()->SetInternalFieldCount(1);
// Set prototype methods
NODE_SET_PROTOTYPE_METHOD(t, "perform_", perform);
NODE_SET_PROTOTYPE_METHOD(t, "setopt_int_", setopt_int);
NODE_SET_PROTOTYPE_METHOD(t, "setopt_str_", setopt_str);
NODE_SET_PROTOTYPE_METHOD(t, "setopt_slist_", setopt_slist);
NODE_SET_PROTOTYPE_METHOD(t, "getinfo_int_", getinfo_int);
NODE_SET_PROTOTYPE_METHOD(t, "getinfo_str_", getinfo_str);
NODE_SET_PROTOTYPE_METHOD(t, "getinfo_double_", getinfo_double);
NODE_SET_PROTOTYPE_METHOD(t, "getinfo_slist_", getinfo_slist);
NODE_SET_PROTOTYPE_METHOD(t, "close", close);
NODE_SET_METHOD(t, "process_", process);
NODE_SET_METHOD(t, "get_count", get_count);
// Set curl constants
#include "string_options.h"
@ -320,11 +407,34 @@ class NodeCurl
#include "integer_infos.h"
#include "double_infos.h"
#define X(name) {#name, CURLOPT_##name}
CurlOption slist_options[] = {
X(HTTPHEADER),
X(HTTP200ALIASES),
X(MAIL_RCPT),
X(QUOTE),
X(POSTQUOTE),
X(PREQUOTE),
X(RESOLVE),
X(TELNETOPTIONS)
};
#undef X
#define X(name) {#name, CURLINFO_##name}
CurlOption slist_infos[] = {
X(SSL_ENGINES),
X(COOKIELIST)
};
#undef X
NODE_CURL_EXPORT(string_options);
NODE_CURL_EXPORT(integer_options);
NODE_CURL_EXPORT(slist_options);
NODE_CURL_EXPORT(string_infos);
NODE_CURL_EXPORT(integer_infos);
NODE_CURL_EXPORT(double_infos);
NODE_CURL_EXPORT(slist_infos);
target->Set(v8::String::NewSymbol("Curl"), t->GetFunction());
return target;
@ -335,5 +445,6 @@ CURLM * NodeCurl::curlm = NULL;
int NodeCurl::running_handles = 0;
bool NodeCurl::is_ref = false;
std::map< CURL*, NodeCurl* > NodeCurl::curls;
int NodeCurl::count = 0;
#endif

View file

@ -4,7 +4,7 @@ def set_options(opt):
def configure(conf):
conf.check_tool('compiler_cxx')
conf.check_tool('node_addon')
conf.env.append_unique('CXXFLAGS', ['-Wall', '-O2', '-std=c++0x'])
conf.env.append_unique('CXXFLAGS', ['-Wall', '-O2'])
conf.env['LIB_CURL'] = 'curl'
def build(bld):