Compare commits
79 commits
Author | SHA1 | Date | |
---|---|---|---|
|
b12a319ebb | ||
|
98bd3a7e61 | ||
|
288400f616 | ||
|
ce4a60be91 | ||
|
1f3a2f1bad | ||
|
5e2abee688 | ||
|
171f5bc3a6 | ||
|
05b8345650 | ||
|
f02c0a6fbf | ||
|
8de753eec9 | ||
|
b77ee78afd | ||
|
5c6e4b0b49 | ||
|
e9e17fc940 | ||
|
5e48419e18 | ||
|
1ba3bb2329 | ||
|
3a42f7f05e | ||
|
788459bc7d | ||
|
b337b6d4fb | ||
|
9c1cbb81c9 | ||
|
e318a72006 | ||
|
8f707b34b1 | ||
|
279e9f04cc | ||
|
78a53743de | ||
|
648e170fa8 | ||
|
91f39f4652 | ||
|
745124ebd6 | ||
|
01dbe4e0ce | ||
|
44fb876123 | ||
|
286b62cc2e | ||
|
e25785eb3f | ||
|
2884985e9a | ||
|
7c776b81a5 | ||
|
decb16d790 | ||
|
ccfb0d4595 | ||
|
1061e177b2 | ||
|
02ba0f25d3 | ||
|
d25438bdf0 | ||
|
2c414d1469 | ||
|
1057195bf5 | ||
|
09c4caae42 | ||
|
3b1ba2a279 | ||
|
579481cac9 | ||
|
9e50c006be | ||
|
54e981182b | ||
|
03e419747d | ||
|
afab82abcf | ||
|
bf0b6555a8 | ||
|
4a7a5feacf | ||
|
b273758a40 | ||
|
e37f47a072 | ||
|
51dfa0ebdf | ||
|
368cc3402b | ||
|
5dc00f43dc | ||
|
a21831a17e | ||
|
2d5e67377b | ||
|
9fe5666c9f | ||
|
6f9d7e24fa | ||
|
829db634a0 | ||
|
d138705419 | ||
|
13f1f69dbc | ||
|
8e0d95d812 | ||
|
e796b240da | ||
|
441b622709 | ||
|
e089e15d85 | ||
|
d92324115c | ||
|
844c70636b | ||
|
c2708fa8a5 | ||
|
7774b9103b | ||
|
e941a326d9 | ||
|
34c42b0ebd | ||
|
c0808d3799 | ||
|
f6bfa11f6e | ||
|
90f3135c8c | ||
|
e791a14c6e | ||
|
49db24b7d4 | ||
|
58acd92ea9 | ||
|
f51c05676c | ||
|
94cef17bf8 | ||
|
f65257623b |
35 changed files with 1374 additions and 674 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
raw
|
||||
build
|
||||
.lock-wscript
|
||||
node_modules
|
||||
|
|
|
@ -2,3 +2,6 @@
|
|||
raw/
|
||||
build/
|
||||
build/.*
|
||||
src/*_infos.h
|
||||
src/*_options.h
|
||||
*.tgz
|
||||
|
|
4
.travis.yml
Normal file
4
.travis.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.8
|
||||
- 0.10
|
22
LICENSE-MIT
Normal file
22
LICENSE-MIT
Normal file
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 2012 Miao Jiang
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
152
README.md
152
README.md
|
@ -1,4 +1,4 @@
|
|||
node-curl
|
||||
node-curl [](http://travis-ci.org/jiangmiao/node-curl)
|
||||
=========
|
||||
|
||||
node cURL wrapper, support all options and infos.
|
||||
|
@ -9,66 +9,95 @@ Quick Start
|
|||
* quick start
|
||||
|
||||
curl = require('node-curl');
|
||||
curl('www.google.com', function(err, res) {
|
||||
console.info(res.status);
|
||||
curl('www.google.com', function(err) {
|
||||
console.info(this.status);
|
||||
console.info('-----');
|
||||
console.info(res.body);
|
||||
console.info(this.body);
|
||||
console.info('-----');
|
||||
console.info(res.info('SIZE_DOWNLOAD'));
|
||||
res.close();
|
||||
console.info(this.info('SIZE_DOWNLOAD'));
|
||||
});
|
||||
|
||||
|
||||
* with options
|
||||
|
||||
curl = require('node-curl')
|
||||
curl('www.google.com', {VERBOSE: 1, RAW: 1}, function(err, res) {
|
||||
console.info(res);
|
||||
res.close();
|
||||
curl('www.google.com', {VERBOSE: 1, RAW: 1}, function(err) {
|
||||
console.info(this);
|
||||
});
|
||||
|
||||
* run the example/test.js
|
||||
|
||||
node examples/test.js
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
* curl
|
||||
|
||||
curl(url, [options = {}], callback)
|
||||
callback includes 2 parameters (error, result)
|
||||
callback includes 1 parameters (error)
|
||||
result is stored in curl
|
||||
|
||||
* result in callback
|
||||
* Retrieve Data from curl
|
||||
|
||||
members:
|
||||
status - Http Response code
|
||||
body - Http body
|
||||
status - Http Response code
|
||||
body - Http body
|
||||
header - Http header
|
||||
|
||||
url - the url set by curl(...)
|
||||
options - the options set by curl(...)
|
||||
defaultOptions - the defaultOptions
|
||||
effectiveOptions - the options curl used
|
||||
|
||||
methods:
|
||||
info(name) - Get information of result, see 'info' section
|
||||
|
||||
REMARK:
|
||||
If the http is redirected, then header will contain at least 2 http headers.
|
||||
|
||||
|
||||
* Curl Control
|
||||
|
||||
members
|
||||
debug (default: false)
|
||||
- logging node-curl debug info
|
||||
|
||||
methods:
|
||||
void reset()
|
||||
- reset curl and set options to default options
|
||||
|
||||
void setDefaultOptions(options, reset = true)
|
||||
- set default options
|
||||
|
||||
curl create(defaultOptions)
|
||||
- create a new curl with default options
|
||||
|
||||
Options
|
||||
-------
|
||||
* Any Curl Easy Options
|
||||
* Any cURL Easy Options
|
||||
|
||||
eg: CURLOPT_VERBOSE will be VERBOSE, CURLOPT_HEADER will be HEADER
|
||||
|
||||
Full list at http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
|
||||
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
|
||||
RAW - Returns Buffer instead of String in result.body
|
||||
DEBUG - Replace curl.debug
|
||||
|
||||
* About slist parameters
|
||||
|
||||
node-curl support slist which map to Javascript Array
|
||||
|
||||
eg:
|
||||
HTTP_HEADER: ['FOO', 'BAR']
|
||||
HTTP_HEADER: 'FOO'
|
||||
eg:
|
||||
HTTPHEADER: ['FOO', 'BAR']
|
||||
HTTPHEADER: 'FOO'
|
||||
|
||||
any non-array parameter will convert to [ parameter.toString() ]
|
||||
|
||||
Infos
|
||||
-----
|
||||
* Any Curl Info options
|
||||
* Any cURL Info options
|
||||
|
||||
eg: CURLINFO_EFFECTIVE_URL will be EFFETCTIVE_URL
|
||||
|
||||
|
@ -80,9 +109,82 @@ Infos
|
|||
slist will be returns in Array
|
||||
eg: CURLINFO_COOKIELIST
|
||||
|
||||
MultiPart Upload
|
||||
----------------
|
||||
Use MULTIPART option
|
||||
|
||||
Hints
|
||||
-----
|
||||
close the result to release resource of curl immediately.
|
||||
There are 4 options in MULTIPART, `name`, `file`, `type`, `contents`
|
||||
|
||||
or the resource will not release until gc performed.
|
||||
```javascript
|
||||
curl('127.0.0.1/upload.php', {
|
||||
MULTIPART: [
|
||||
{name: 'file', file: '/file/path', type: 'text/html'},
|
||||
{name: 'sumbit', contents: 'send'}
|
||||
]
|
||||
}, function(e) {
|
||||
console.log(e);
|
||||
console.log(this.body);
|
||||
this.close()
|
||||
});
|
||||
```
|
||||
|
||||
Low Level Curl Usage
|
||||
--------------------
|
||||
|
||||
require 'node-curl/lib/Curl'
|
||||
|
||||
Methods:
|
||||
|
||||
Curl setopt(optionName, optionValue)
|
||||
Curl perform()
|
||||
Curl on(eventType, callback)
|
||||
Mixed getinfo(infoName)
|
||||
|
||||
Events:
|
||||
|
||||
'data', function(Buffer chunk) {}
|
||||
'header', function(Buffer chunk) {}
|
||||
'error', function(Error error) {}
|
||||
'end', function() {}
|
||||
|
||||
Example: examples/low-level.js
|
||||
|
||||
var Curl = require('node-curl/lib/Curl')
|
||||
|
||||
var p = console.log;
|
||||
var url = process.argv[2];
|
||||
|
||||
var curl = new Curl();
|
||||
|
||||
if (!url)
|
||||
url = 'www.yahoo.com';
|
||||
|
||||
curl.setopt('URL', url);
|
||||
curl.setopt('CONNECTTIMEOUT', 2);
|
||||
|
||||
// on 'data' must be returns chunk.length, or means interrupt the transfer
|
||||
curl.on('data', function(chunk) {
|
||||
p("receive " + chunk.length);
|
||||
return chunk.length;
|
||||
});
|
||||
|
||||
curl.on('header', function(chunk) {
|
||||
p("receive header " + chunk.length);
|
||||
return chunk.length;
|
||||
})
|
||||
|
||||
// curl.close() should be called in event 'error' and 'end' if the curl won't use any more.
|
||||
// or the resource will not release until V8 garbage mark sweep.
|
||||
curl.on('error', function(e) {
|
||||
p("error: " + e.message);
|
||||
curl.close();
|
||||
});
|
||||
|
||||
|
||||
curl.on('end', function() {
|
||||
p('code: ' + curl.getinfo('RESPONSE_CODE'));
|
||||
p('done.');
|
||||
curl.close();
|
||||
});
|
||||
|
||||
curl.perform();
|
||||
|
|
11
binding.gyp
Normal file
11
binding.gyp
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'node-curl',
|
||||
'cflags': ['-Wall', '-O1', '-g', '-fno-inline-functions'],
|
||||
'cflags_cc': ['-Wall', '-O1', '-g', '-fno-inline-functions'],
|
||||
'sources': ['src/node-curl.cc'],
|
||||
'libraries': ['-lcurl']
|
||||
}
|
||||
]
|
||||
}
|
23
examples/curl.js
Normal file
23
examples/curl.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Generated by ToffeeScript 1.6.2-5
|
||||
(function() {
|
||||
var curl, err, p, res,
|
||||
_this = this;
|
||||
|
||||
curl = require('../index');
|
||||
|
||||
p = console.info;
|
||||
|
||||
curl(process.argv[2], {
|
||||
VERBOSE: 1,
|
||||
DEBUG: 1,
|
||||
FOLLOWLOCATION: 1
|
||||
}, function() {
|
||||
err = arguments[0], res = arguments[1];
|
||||
if (err) {
|
||||
return p(err);
|
||||
} else {
|
||||
return p(res);
|
||||
}
|
||||
});
|
||||
|
||||
}).call(this);
|
8
examples/curl.toffee
Normal file
8
examples/curl.toffee
Normal file
|
@ -0,0 +1,8 @@
|
|||
curl = require '../index'
|
||||
p = console.info
|
||||
|
||||
err, res = curl! process.argv[2], {VERBOSE: 1, DEBUG: 1, FOLLOWLOCATION: 1}
|
||||
if err
|
||||
p err
|
||||
else
|
||||
p res
|
40
examples/low-level.js
Normal file
40
examples/low-level.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
var Curl = require('../lib/Curl');
|
||||
|
||||
var p = console.log;
|
||||
var url = process.argv[2];
|
||||
|
||||
var curl = new Curl();
|
||||
|
||||
if (!url)
|
||||
url = 'www.yahoo.com';
|
||||
|
||||
curl.setopt('URL', url);
|
||||
curl.setopt('CONNECTTIMEOUT', 2);
|
||||
curl.setopt('VERBOSE', 1);
|
||||
|
||||
// on 'data' must be returns chunk.length, or means interrupt the transfer
|
||||
curl.on('data', function(chunk) {
|
||||
p("receive " + chunk.length);
|
||||
return chunk.length;
|
||||
});
|
||||
|
||||
curl.on('header', function(chunk) {
|
||||
p("receive header " + chunk.length);
|
||||
return chunk.length;
|
||||
})
|
||||
|
||||
// curl.close() should be called in event 'error' and 'end' if the curl won't use any more.
|
||||
// or the resource will not release until V8 garbage mark sweep.
|
||||
curl.on('error', function(e) {
|
||||
p("error: " + e.message);
|
||||
curl.close();
|
||||
});
|
||||
|
||||
|
||||
curl.on('end', function() {
|
||||
p('code: ' + curl.getinfo('RESPONSE_CODE'));
|
||||
p('done.');
|
||||
curl.close();
|
||||
});
|
||||
|
||||
curl.perform();
|
28
examples/post-multi-part.js
Normal file
28
examples/post-multi-part.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Generated by ToffeeScript 1.6.2-5
|
||||
(function() {
|
||||
var curl, p;
|
||||
|
||||
curl = require('../index');
|
||||
|
||||
p = console.log;
|
||||
|
||||
p('start');
|
||||
|
||||
curl('127.0.0.1/upload.php', {
|
||||
multipart: [
|
||||
{
|
||||
name: 'file',
|
||||
file: '/home/miao/test.js',
|
||||
type: 'text/html'
|
||||
}, {
|
||||
name: 'sumbit',
|
||||
contents: 'send'
|
||||
}
|
||||
]
|
||||
}, function(e) {
|
||||
console.log(e);
|
||||
console.log(this.body);
|
||||
return this.close();
|
||||
});
|
||||
|
||||
}).call(this);
|
13
examples/post-multi-part.toffee
Normal file
13
examples/post-multi-part.toffee
Normal file
|
@ -0,0 +1,13 @@
|
|||
curl = require '../index'
|
||||
p = console.log
|
||||
p 'start'
|
||||
|
||||
curl '127.0.0.1/upload.php', {
|
||||
multipart: [
|
||||
{name: 'file', file: '/home/miao/test.js', type: 'text/html'},
|
||||
{name: 'sumbit', contents: 'send'}
|
||||
],
|
||||
}, (e) ->
|
||||
console.log e
|
||||
console.log @body
|
||||
@close()
|
|
@ -1,30 +1,38 @@
|
|||
// Generated by ToffeeScript 1.1.4-4
|
||||
// Generated by ToffeeScript 1.6.2-5
|
||||
(function() {
|
||||
var assert, curl, i, j, next, once, _i;
|
||||
var Curl, assert, i, j, next, _fn, _i;
|
||||
|
||||
curl = require('../index');
|
||||
Curl = require('../index');
|
||||
|
||||
assert = require('assert');
|
||||
|
||||
j = 0;
|
||||
|
||||
(next = function() {
|
||||
console.info("curl instances: ", curl.get_count());
|
||||
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;
|
||||
_fn = function() {
|
||||
var curl, once;
|
||||
curl = Curl.create();
|
||||
return (once = function() {
|
||||
var err, res,
|
||||
_this = this;
|
||||
curl('localhost/test.html', function() {
|
||||
err = arguments[0], res = arguments[1];
|
||||
assert.equal(res.body.length, 1468);
|
||||
if (++j % 100 === 0) console.info(j);
|
||||
if (j < 20000) return once();
|
||||
if (++j % 100 === 0) {
|
||||
console.info(j);
|
||||
}
|
||||
if (j < 500000) {
|
||||
return once();
|
||||
}
|
||||
});
|
||||
})();
|
||||
};
|
||||
for (i = _i = 1; _i <= 100; i = ++_i) {
|
||||
_fn();
|
||||
}
|
||||
|
||||
}).call(this);
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
curl = require '../index'
|
||||
Curl = require '../index'
|
||||
assert = require 'assert'
|
||||
j = 0;
|
||||
do next = ->
|
||||
console.info "curl instances: ", curl.get_count()
|
||||
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()
|
||||
do ->
|
||||
curl = Curl.create()
|
||||
do once = ->
|
||||
err, res = curl! 'localhost/test.html'
|
||||
assert.equal res.body.length, 1468
|
||||
if ++j % 100 == 0
|
||||
console.info j
|
||||
if j < 500000
|
||||
once()
|
||||
# res.close()
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
curl = require('../index');
|
||||
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);
|
||||
res.close();
|
||||
|
||||
// second argument 'options' is omitted.
|
||||
url = 'www.google.com';
|
||||
console.info("GET " + url);
|
||||
curl('www.google.com', function(err) {
|
||||
console.info("\x1b[32mGet " + this.url + " finished.\x1b[0m");
|
||||
console.info("\tstatus: " + this.status);
|
||||
console.info("\tbody length: " + this.body.length);
|
||||
console.info("\tinfo SIZE_DOWNLOAD: " + this.info('SIZE_DOWNLOAD'));
|
||||
console.info("\tinfo EFFECTIVE_URL " + this.info('EFFECTIVE_URL'));
|
||||
this.close();
|
||||
});
|
||||
|
||||
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();
|
||||
// because we uses curl in parallel. and each curl is only for one session.
|
||||
// so use curl.create(defaultOptions = {}) to create new curl/session.
|
||||
curl2 = curl.create({RAW: 1});
|
||||
url2 = 'www.google.com';
|
||||
options2 = {FOLLOWLOCATION: 1};
|
||||
console.info("GET " + url + " with default options " + JSON.stringify(curl2.defaultOptions) + ' and options ' + JSON.stringify(options2));
|
||||
curl2(url2, options2, function(err) {
|
||||
console.info("\x1b[32mGet " + this.url + " with " + JSON.stringify(this.effectiveOptions) + " finished.\x1b[0m");
|
||||
console.info("\tstatus: " + this.status);
|
||||
console.info("\tbody length: " + this.body.length);
|
||||
console.info("\tinfo SIZE_DOWNLOAD: " + this.info('SIZE_DOWNLOAD'));
|
||||
console.info("\tinfo EFFECTIVE_URL " + this.info('EFFECTIVE_URL'));
|
||||
this.close();
|
||||
});
|
||||
|
||||
curl('https://www.google.com', {VERBOSE: 1, RAW: 1}, function(err, res) {
|
||||
console.info("\x1b[33meffetcive url: " + res.info('EFFECTIVE_URL') + "\x1b[0m");
|
||||
console.info(res);
|
||||
res.close();
|
||||
});
|
||||
|
||||
/*
|
||||
console.info('-----');
|
||||
console.info("status: " + res.status);
|
||||
console.info('-----');
|
||||
console.info("size download: " + res.info('SIZE_DOWNLOAD'));
|
||||
*/
|
||||
|
|
45
examples/test-get-info.js
Normal file
45
examples/test-get-info.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
Curl = require('../index');
|
||||
|
||||
defaultOptions = {CONNECTTIMEOUT: 2};
|
||||
keys = ["EFFECTIVE_URL", "CONTENT_TYPE", "PRIVATE", "FTP_ENTRY_PATH", "REDIRECT_URL", "PRIMARY_IP", "RTSP_SESSION_ID", "LOCAL_IP"];
|
||||
|
||||
function print(text, color) {
|
||||
if (!/^\d+$/.test(color)) {
|
||||
color = {red: 31, green: 32, yellow: 33}[color];
|
||||
}
|
||||
|
||||
if (!color)
|
||||
return console.info(text);
|
||||
|
||||
console.info("\x1b[" + color + "m" + text + "\x1b[0m");
|
||||
}
|
||||
|
||||
requests = [
|
||||
['www.nodejs.org'],
|
||||
['www.yahoo.com'],
|
||||
['https://www.google.com', {VERBOSE: 1, RAW: 1}]
|
||||
];
|
||||
|
||||
requests.forEach(function(request) {
|
||||
url = request[0];
|
||||
options = request[1];
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
curl = Curl.create(defaultOptions);
|
||||
print('GET ' + url, 'green')
|
||||
curl(url, options, function(err) {
|
||||
print('GET ' + this.url + ' ' + JSON.stringify(this.effectiveOptions) + " finished.", 'green');
|
||||
|
||||
if (err)
|
||||
return print(err, 'red');
|
||||
|
||||
self = this;
|
||||
keys.forEach(function(key) {
|
||||
print("\t" + key + ": [" + self.info(key) + "]", 'yellow');
|
||||
})
|
||||
|
||||
print("\tbody length: " + this.body.length);
|
||||
this.close();
|
||||
});
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
// Generated by ToffeeScript 1.1.4-4
|
||||
// Generated by ToffeeScript 1.6.2-5
|
||||
(function() {
|
||||
var curl, fs, p, url, util,
|
||||
var cookieFile, curl, err, fs, options, p, stream, util,
|
||||
_this = this;
|
||||
|
||||
curl = require('../index');
|
||||
|
@ -11,29 +11,41 @@
|
|||
|
||||
p = console.info;
|
||||
|
||||
url = 'www.google.com';
|
||||
cookieFile = 'node-curl-cookie.txt';
|
||||
|
||||
curl(url, {
|
||||
HTTPHEADER: 'BAR',
|
||||
options = {
|
||||
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');
|
||||
COOKIEFILE: cookieFile,
|
||||
COOKIEJAR: cookieFile,
|
||||
ACCEPT_ENCODING: 'gzip',
|
||||
RAW: 1
|
||||
};
|
||||
|
||||
curl.debug = 1;
|
||||
|
||||
curl.setDefaultOptions(options);
|
||||
|
||||
curl('www.google.com', function() {
|
||||
err = arguments[0];
|
||||
p("\x1b[33m" + util.inspect(curl.info('COOKIELIST')) + "\x1b[0m");
|
||||
curl.reset();
|
||||
curl('www.yahoo.com', function() {
|
||||
err = arguments[0];
|
||||
p("\x1b[33m" + util.inspect(curl.info('COOKIELIST')) + "\x1b[0m");
|
||||
p("body length " + curl.body.length);
|
||||
p("\x1b[33mText in " + cookieFile + "\x1b[0m");
|
||||
p("----");
|
||||
stream = fs.createReadStream(cookieFile);
|
||||
stream.pipe(process.stdout);
|
||||
return stream.on('end', function() {
|
||||
var _this = this;
|
||||
p("----");
|
||||
curl.close();
|
||||
p("deleting " + cookieFile);
|
||||
fs.unlink(cookieFile, function() {
|
||||
return p("done.");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -3,20 +3,29 @@ fs = require 'fs'
|
|||
util = require 'util'
|
||||
p = console.info
|
||||
|
||||
url = 'www.google.com'
|
||||
err, res = curl! url,
|
||||
HTTPHEADER: 'BAR'
|
||||
cookieFile = 'node-curl-cookie.txt'
|
||||
options = {
|
||||
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'
|
||||
COOKIEFILE: cookieFile
|
||||
COOKIEJAR: cookieFile
|
||||
ACCEPT_ENCODING: 'gzip'
|
||||
RAW: 1
|
||||
|
||||
p "\x1b[33m" + util.inspect(res.info('COOKIELIST')) + "\x1b[0m"
|
||||
p res.body
|
||||
fs.unlink 'node-curl-cookie.txt'
|
||||
}
|
||||
curl.debug = 1
|
||||
curl.setDefaultOptions options
|
||||
err = curl! 'www.google.com'
|
||||
p "\x1b[33m" + util.inspect(curl.info('COOKIELIST')) + "\x1b[0m"
|
||||
curl.reset()
|
||||
err = curl! 'www.yahoo.com'
|
||||
p "\x1b[33m" + util.inspect(curl.info('COOKIELIST')) + "\x1b[0m"
|
||||
p "body length #{curl.body.length}"
|
||||
p "\x1b[33mText in #{cookieFile}\x1b[0m"
|
||||
p "----"
|
||||
stream = fs.createReadStream(cookieFile)
|
||||
stream.pipe(process.stdout)
|
||||
stream.on 'end', ->
|
||||
p "----"
|
||||
curl.close()
|
||||
p "deleting #{cookieFile}"
|
||||
fs.unlink! cookieFile
|
||||
p "done."
|
||||
|
|
7
index.js
7
index.js
|
@ -1,6 +1,9 @@
|
|||
// Generated by CoffeeScript 1.1.4-3
|
||||
// Generated by ToffeeScript 1.4.0
|
||||
(function() {
|
||||
var CurlBuilder;
|
||||
|
||||
module.exports = require('./lib/curl');
|
||||
CurlBuilder = require('./lib/CurlBuilder');
|
||||
|
||||
module.exports = CurlBuilder.create();
|
||||
|
||||
}).call(this);
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
module.exports = require './lib/curl'
|
||||
CurlBuilder = require './lib/CurlBuilder'
|
||||
module.exports = CurlBuilder.create()
|
||||
|
|
174
lib/Curl.js
Normal file
174
lib/Curl.js
Normal file
|
@ -0,0 +1,174 @@
|
|||
// Generated by ToffeeScript 1.6.2-5
|
||||
(function() {
|
||||
var Curl, curls, e, id, m, p,
|
||||
__hasProp = {}.hasOwnProperty;
|
||||
|
||||
try {
|
||||
Curl = require(__dirname + '/../build/Release/node-curl').Curl;
|
||||
} catch (_error) {
|
||||
e = _error;
|
||||
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_httppost = function(rows) {
|
||||
var cols, k, option_id, row, v;
|
||||
this.httppost = (function() {
|
||||
var _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = rows.length; _i < _len; _i++) {
|
||||
row = rows[_i];
|
||||
cols = [];
|
||||
for (k in row) {
|
||||
if (!__hasProp.call(row, k)) continue;
|
||||
v = row[k];
|
||||
k = k.toUpperCase();
|
||||
if ((option_id = Curl.httppost_options[k]) != null) {
|
||||
cols.push(option_id);
|
||||
if (!(v instanceof Buffer)) {
|
||||
v = new Buffer(v.toString());
|
||||
}
|
||||
cols.push(v);
|
||||
} else {
|
||||
throw new Error("invalid http post option " + k);
|
||||
}
|
||||
}
|
||||
_results.push(cols);
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
this.setopt_httppost_(this.httppost);
|
||||
return this;
|
||||
};
|
||||
|
||||
Curl.prototype.setopt = function(option_name, value) {
|
||||
var option, option_id;
|
||||
option = option_name.toUpperCase();
|
||||
if ((option_id = Curl.user_options[option]) != null) {
|
||||
if (option === 'MULTIPART') {
|
||||
this.setopt_httppost(value);
|
||||
} else {
|
||||
this.setopt_user_(option_id, value);
|
||||
}
|
||||
} else if ((option_id = Curl.slist_options[option]) != null) {
|
||||
this.setopt_slist_(option_id, value);
|
||||
} else if ((option_id = Curl.integer_options[option]) != null) {
|
||||
this.setopt_int_(option_id, value >> 0);
|
||||
} else if ((option_id = Curl.string_options[option]) != null) {
|
||||
if (value == null) {
|
||||
throw new Error("Cannot set option " + option_name + " to " + value + ".");
|
||||
}
|
||||
this.setopt_str_(option_id, value.toString());
|
||||
} else {
|
||||
throw new Error("unsupported option " + option);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Curl.prototype.getinfo = function(oinfo) {
|
||||
var info, info_id;
|
||||
info = oinfo.toUpperCase();
|
||||
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("unsupported info " + oinfo);
|
||||
}
|
||||
};
|
||||
|
||||
Curl.user_options = {
|
||||
RAW: 'RAW',
|
||||
DEBUG: 'DEBUG',
|
||||
MULTIPART: 'MULTIPART'
|
||||
};
|
||||
|
||||
id = 0;
|
||||
|
||||
curls = {};
|
||||
|
||||
Curl.prototype.on = function(event, callback) {
|
||||
var _this = this;
|
||||
switch (event) {
|
||||
case 'data':
|
||||
this.on_write = function(chunk) {
|
||||
return callback.call(_this, chunk);
|
||||
};
|
||||
break;
|
||||
case 'header':
|
||||
this.on_header = function(chunk) {
|
||||
return callback.call(_this, chunk);
|
||||
};
|
||||
break;
|
||||
case 'error':
|
||||
this.on_error = function(e) {
|
||||
delete curls[_this.id];
|
||||
return callback.call(_this, e);
|
||||
};
|
||||
break;
|
||||
case 'end':
|
||||
this.on_end = function() {
|
||||
delete curls[_this.id];
|
||||
return callback.call(_this);
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new Error("invalid event type " + event);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Curl.prototype.close = function() {
|
||||
delete curls[this.id];
|
||||
return this.close_();
|
||||
};
|
||||
|
||||
Curl.prototype.perform = function() {
|
||||
this.id = ++id;
|
||||
curls[this.id] = this;
|
||||
this.perform_();
|
||||
Curl.process();
|
||||
return this;
|
||||
};
|
||||
|
||||
m = 0;
|
||||
|
||||
p = console.log;
|
||||
|
||||
Curl.process = function() {
|
||||
var once;
|
||||
if (Curl.in_process) {
|
||||
return;
|
||||
}
|
||||
return (once = function() {
|
||||
var n, w;
|
||||
n = Curl.process_();
|
||||
if (n > 0) {
|
||||
Curl.in_process = true;
|
||||
if (n > 8192 && m < 10) {
|
||||
++m;
|
||||
return process.nextTick(once);
|
||||
} else {
|
||||
m = 0;
|
||||
w = (8192 - n) * 80 / 8192 >> 0;
|
||||
if (w < 0) {
|
||||
w = 0;
|
||||
}
|
||||
return setTimeout(once, w);
|
||||
}
|
||||
} else {
|
||||
return Curl.in_process = false;
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
module.exports = Curl;
|
||||
|
||||
}).call(this);
|
133
lib/Curl.toffee
Normal file
133
lib/Curl.toffee
Normal file
|
@ -0,0 +1,133 @@
|
|||
try
|
||||
{Curl} = require __dirname + '/../build/Release/node-curl'
|
||||
catch e
|
||||
{Curl} = require __dirname + '/../build/default/node-curl'
|
||||
|
||||
Curl::setopt_user_ = (option_id, value) ->
|
||||
@options[option_id] = value
|
||||
|
||||
Curl::setopt_httppost = (rows) ->
|
||||
# convert object-rows to array-rows
|
||||
# format
|
||||
# [
|
||||
# [OPTION_ID, VALUE]
|
||||
# ]
|
||||
@httppost = for row in rows
|
||||
cols = []
|
||||
for own k, v of row
|
||||
k = k.toUpperCase()
|
||||
if (option_id = Curl.httppost_options[k])?
|
||||
cols.push option_id
|
||||
unless v instanceof Buffer
|
||||
v = new Buffer(v.toString())
|
||||
cols.push v
|
||||
else
|
||||
throw new Error("invalid http post option #{k}")
|
||||
cols
|
||||
@setopt_httppost_(@httppost)
|
||||
@
|
||||
|
||||
|
||||
Curl::setopt = (option_name, value) ->
|
||||
option = option_name.toUpperCase()
|
||||
|
||||
# slist must be at the top of condition
|
||||
# the option exists in string_options too
|
||||
if (option_id = Curl.user_options[option])?
|
||||
if (option == 'MULTIPART')
|
||||
@setopt_httppost value
|
||||
else
|
||||
@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])?
|
||||
if !value?
|
||||
throw new Error("Cannot set option #{option_name} to #{value}.")
|
||||
@setopt_str_ option_id, value.toString()
|
||||
else
|
||||
throw new Error("unsupported option #{option}")
|
||||
@
|
||||
|
||||
Curl::getinfo = (oinfo) ->
|
||||
info = oinfo.toUpperCase()
|
||||
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("unsupported info #{oinfo}")
|
||||
|
||||
Curl.user_options =
|
||||
RAW: 'RAW'
|
||||
DEBUG: 'DEBUG'
|
||||
MULTIPART: 'MULTIPART'
|
||||
|
||||
id = 0
|
||||
curls = {}
|
||||
|
||||
# on 'data' must be returns the chunk length
|
||||
Curl::on = (event, callback) ->
|
||||
switch event
|
||||
when 'data'
|
||||
# (Buffer chunk) ->
|
||||
@on_write = (chunk) =>
|
||||
callback.call @, chunk
|
||||
when 'header'
|
||||
@on_header = (chunk) =>
|
||||
callback.call @, chunk
|
||||
when 'error'
|
||||
# (Error error) ->
|
||||
@on_error = (e) =>
|
||||
delete curls[@id]
|
||||
callback.call @, e
|
||||
when 'end'
|
||||
# () ->
|
||||
@on_end = =>
|
||||
delete curls[@id]
|
||||
callback.call @
|
||||
else
|
||||
throw new Error("invalid event type #{event}")
|
||||
@
|
||||
|
||||
Curl::close = () ->
|
||||
delete curls[@id]
|
||||
@close_()
|
||||
|
||||
Curl::perform = ->
|
||||
@id = ++id
|
||||
curls[@id] = @
|
||||
@perform_()
|
||||
Curl.process()
|
||||
@
|
||||
|
||||
m = 0
|
||||
p = console.log
|
||||
Curl.process = ->
|
||||
if Curl.in_process
|
||||
return
|
||||
do once = ->
|
||||
n = Curl.process_()
|
||||
if n > 0
|
||||
Curl.in_process = true
|
||||
if n > 8192 && m < 10
|
||||
++m
|
||||
process.nextTick once
|
||||
else
|
||||
m = 0
|
||||
w = (8192 - n) * 80 / 8192 >> 0
|
||||
if w < 0
|
||||
w = 0
|
||||
setTimeout once, w
|
||||
else
|
||||
Curl.in_process = false
|
||||
|
||||
|
||||
|
||||
module.exports = Curl
|
||||
# vim: sw=2 ts=2 sts=2 expandtab :
|
222
lib/CurlBuilder.js
Normal file
222
lib/CurlBuilder.js
Normal file
|
@ -0,0 +1,222 @@
|
|||
// Generated by ToffeeScript 1.6.2-5
|
||||
(function() {
|
||||
var Curl, CurlBuilder, e,
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__slice = [].slice;
|
||||
|
||||
try {
|
||||
Curl = require(__dirname + '/Curl');
|
||||
} catch (_error) {
|
||||
e = _error;
|
||||
Curl = require(__dirname + '/Curl');
|
||||
}
|
||||
|
||||
function merge_chunks(chunks, length) {
|
||||
var chunk, data, position, _i, _len;
|
||||
data = new Buffer(length);
|
||||
position = 0;
|
||||
for (_i = 0, _len = chunks.length; _i < _len; _i++) {
|
||||
chunk = chunks[_i];
|
||||
chunk.copy(data, position);
|
||||
position += chunk.length;
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
CurlBuilder = (function() {
|
||||
function CurlBuilder() {}
|
||||
|
||||
CurlBuilder.curls = {};
|
||||
|
||||
CurlBuilder.id = 0;
|
||||
|
||||
CurlBuilder.close_all = function() {
|
||||
var curl, id, _ref;
|
||||
_ref = CurlBuilder.curls;
|
||||
for (id in _ref) {
|
||||
if (!__hasProp.call(_ref, id)) continue;
|
||||
curl = _ref[id];
|
||||
curl.end();
|
||||
delete CurlBuilder.curls[id];
|
||||
}
|
||||
return CurlBuilder;
|
||||
};
|
||||
|
||||
CurlBuilder.create = function(defaultOptions) {
|
||||
function curl() {
|
||||
return curl.perform.apply(curl, arguments);
|
||||
};
|
||||
curl.perform = function() {
|
||||
var args, c, cb, header_length, k, length, v, _ref, _ref1, _ref2, _ref3, _ref4;
|
||||
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
||||
if (this.running) {
|
||||
throw new Error('the cURL session is busy, use curl.create to create another cURL Session');
|
||||
}
|
||||
if (!this.curl_) {
|
||||
throw new Error('the cURL is closed.');
|
||||
}
|
||||
this.running = true;
|
||||
cb = args.pop();
|
||||
this.url = args[0], this.options = args[1];
|
||||
if ((_ref = this.options) == null) {
|
||||
this.options = {};
|
||||
}
|
||||
length = 0;
|
||||
header_length = 0;
|
||||
this.debug = (_ref1 = (_ref2 = this.defaultOptions.DEBUG) != null ? _ref2 : this.options.DEBUG) != null ? _ref1 : this.debug;
|
||||
this.effectiveOptions = {};
|
||||
_ref3 = this.defaultOptions;
|
||||
for (k in _ref3) {
|
||||
v = _ref3[k];
|
||||
this.effectiveOptions[k] = v;
|
||||
}
|
||||
_ref4 = this.options;
|
||||
for (k in _ref4) {
|
||||
v = _ref4[k];
|
||||
this.effectiveOptions[k] = v;
|
||||
}
|
||||
this.setOptions(this.effectiveOptions);
|
||||
this.setOptions({
|
||||
URL: this.url
|
||||
});
|
||||
c = this.curl_;
|
||||
c.chunks = [];
|
||||
c.header_chunks = [];
|
||||
c.on('data', function(chunk) {
|
||||
curl.log("receive " + chunk.length + " bytes");
|
||||
c.chunks.push(chunk);
|
||||
length += chunk.length;
|
||||
return chunk.length;
|
||||
});
|
||||
c.on('header', function(chunk) {
|
||||
curl.log("receive " + chunk.length + " header");
|
||||
c.header_chunks.push(chunk);
|
||||
header_length += chunk.length;
|
||||
return chunk.length;
|
||||
});
|
||||
c.on('end', function() {
|
||||
var data, header,
|
||||
_this = this;
|
||||
curl.log("receive succeeded.");
|
||||
curl.running = false;
|
||||
data = merge_chunks(c.chunks, length);
|
||||
header = merge_chunks(c.header_chunks, header_length);
|
||||
c.chunks = [];
|
||||
c.header_chunks = [];
|
||||
if (c.options.RAW) {
|
||||
curl.body = data;
|
||||
curl.header = header;
|
||||
} else {
|
||||
curl.body = data.toString();
|
||||
curl.header = header.toString();
|
||||
}
|
||||
curl.status = curl.code = c.getinfo('RESPONSE_CODE');
|
||||
process.nextTick(function() {
|
||||
return cb.call(curl, null, curl);
|
||||
});
|
||||
});
|
||||
c.on('error', function(err) {
|
||||
var _this = this;
|
||||
curl.log("receive failed: " + err.message);
|
||||
curl.running = false;
|
||||
process.nextTick(function() {
|
||||
return cb.call(curl, err, null);
|
||||
});
|
||||
});
|
||||
this.log('perform');
|
||||
return c.perform();
|
||||
};
|
||||
curl.setDefaultOptions = function(options, reset) {
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
if (reset == null) {
|
||||
reset = true;
|
||||
}
|
||||
defaultOptions = options;
|
||||
if (reset) {
|
||||
this.log('Set default options and reset cURL');
|
||||
return this.reset();
|
||||
}
|
||||
};
|
||||
curl.log = function(text) {
|
||||
if (this.debug) {
|
||||
return console.info(("[cURL " + this.id + "] ") + text);
|
||||
}
|
||||
};
|
||||
curl.setOptions = function(options) {
|
||||
var k, v;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
for (k in options) {
|
||||
if (!__hasProp.call(options, k)) continue;
|
||||
v = options[k];
|
||||
this.log("Set option '" + k + "' to '" + v + "'");
|
||||
this.curl_.setopt(k, v);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
curl.setopts = function(options) {
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
return this.setOptions(options);
|
||||
};
|
||||
curl.info = function(info) {
|
||||
if (this.curl_ == null) {
|
||||
throw new Error('curl is closed');
|
||||
}
|
||||
return this.curl_.getinfo(info);
|
||||
};
|
||||
curl.end = function() {
|
||||
if (this.curl_ != null) {
|
||||
this.curl_.close();
|
||||
}
|
||||
this.curl_ = null;
|
||||
this.body = null;
|
||||
delete CurlBuilder.curls[this.id];
|
||||
return this.log("closed.");
|
||||
};
|
||||
curl.close = function() {
|
||||
return this.end();
|
||||
};
|
||||
curl.open = function() {
|
||||
if (curl.id == null) {
|
||||
curl.id = ++CurlBuilder.id;
|
||||
}
|
||||
this.log("opening.");
|
||||
this.curl_ = new Curl();
|
||||
this.curl_.options = {};
|
||||
this.defaultOptions = defaultOptions != null ? defaultOptions : {};
|
||||
CurlBuilder.curls[curl.id] = curl;
|
||||
return this.log("opened.");
|
||||
};
|
||||
curl.reset = function() {
|
||||
this.log('reset');
|
||||
if (this.curl_) {
|
||||
this.end();
|
||||
}
|
||||
return this.open();
|
||||
};
|
||||
curl.create = function(defaultOptions) {
|
||||
return CurlBuilder.create(defaultOptions);
|
||||
};
|
||||
curl.get_count = function() {
|
||||
return Curl.get_count();
|
||||
};
|
||||
curl.open();
|
||||
return curl;
|
||||
};
|
||||
|
||||
return CurlBuilder;
|
||||
|
||||
}).call(this);
|
||||
|
||||
process.on('exit', function() {
|
||||
return CurlBuilder.close_all();
|
||||
});
|
||||
|
||||
module.exports = CurlBuilder;
|
||||
|
||||
}).call(this);
|
165
lib/CurlBuilder.toffee
Normal file
165
lib/CurlBuilder.toffee
Normal file
|
@ -0,0 +1,165 @@
|
|||
try
|
||||
Curl = require __dirname + '/Curl'
|
||||
catch e
|
||||
Curl = require __dirname + '/Curl'
|
||||
|
||||
merge_chunks = (chunks, length) ->
|
||||
data = new Buffer(length)
|
||||
position = 0
|
||||
for chunk in chunks
|
||||
chunk.copy data, position
|
||||
position += chunk.length
|
||||
data
|
||||
|
||||
class CurlBuilder
|
||||
@curls: {}
|
||||
@id: 0
|
||||
@close_all: =>
|
||||
for own id, curl of @curls
|
||||
curl.end()
|
||||
delete @curls[id]
|
||||
@
|
||||
|
||||
@create: (defaultOptions) =>
|
||||
curl = ->
|
||||
curl.perform.apply curl, arguments
|
||||
|
||||
curl.perform = (args...) ->
|
||||
if @running
|
||||
throw new Error 'the cURL session is busy, use curl.create to create another cURL Session'
|
||||
|
||||
if !@curl_
|
||||
throw new Error 'the cURL is closed.'
|
||||
|
||||
@running = true
|
||||
|
||||
# pop arguments (url, [options = {}], callback)
|
||||
cb = args.pop()
|
||||
[@url, @options] = args
|
||||
@options ?= {}
|
||||
|
||||
length = 0
|
||||
header_length = 0
|
||||
|
||||
@debug = @defaultOptions.DEBUG ? @options.DEBUG ? @debug
|
||||
@effectiveOptions = {}
|
||||
for k, v of @defaultOptions
|
||||
@effectiveOptions[k] = v
|
||||
|
||||
for k, v of @options
|
||||
@effectiveOptions[k] = v
|
||||
|
||||
@setOptions @effectiveOptions
|
||||
@setOptions {URL: @url}
|
||||
|
||||
c = @curl_
|
||||
c.chunks = []
|
||||
c.header_chunks = []
|
||||
c.on 'data', (chunk) ->
|
||||
curl.log "receive #{chunk.length} bytes"
|
||||
c.chunks.push chunk
|
||||
length += chunk.length
|
||||
chunk.length
|
||||
|
||||
c.on 'header', (chunk) ->
|
||||
curl.log "receive #{chunk.length} header"
|
||||
c.header_chunks.push chunk
|
||||
header_length += chunk.length
|
||||
chunk.length
|
||||
|
||||
c.on 'end', ->
|
||||
curl.log "receive succeeded."
|
||||
curl.running = false
|
||||
data = merge_chunks(c.chunks, length)
|
||||
header = merge_chunks(c.header_chunks, header_length)
|
||||
c.chunks = []
|
||||
c.header_chunks = []
|
||||
|
||||
if c.options.RAW
|
||||
curl.body = data
|
||||
curl.header = header
|
||||
else
|
||||
curl.body = data.toString()
|
||||
curl.header = header.toString()
|
||||
curl.status = curl.code = c.getinfo('RESPONSE_CODE')
|
||||
|
||||
# if curl returns to fast, avoid cb recursive call
|
||||
process.nextTick!
|
||||
cb.call curl, null, curl
|
||||
|
||||
c.on 'error', (err)->
|
||||
curl.log "receive failed: #{err.message}"
|
||||
curl.running = false
|
||||
process.nextTick!
|
||||
cb.call curl, err, null
|
||||
|
||||
@log 'perform'
|
||||
c.perform()
|
||||
|
||||
|
||||
|
||||
curl.setDefaultOptions = (options = {}, reset = true) ->
|
||||
defaultOptions = options
|
||||
if reset
|
||||
@log 'Set default options and reset cURL'
|
||||
@reset()
|
||||
|
||||
curl.log = (text) ->
|
||||
if @debug
|
||||
console.info "[cURL #{@id}] " + text
|
||||
|
||||
curl.setOptions = (options = {}) ->
|
||||
for own k, v of options
|
||||
@log "Set option '#{k}' to '#{v}'"
|
||||
@curl_.setopt k, v
|
||||
@
|
||||
|
||||
curl.setopts = (options = {}) ->
|
||||
@setOptions options
|
||||
|
||||
curl.info = (info)->
|
||||
unless @curl_?
|
||||
throw new Error('curl is closed')
|
||||
@curl_.getinfo(info)
|
||||
|
||||
curl.end = ->
|
||||
@curl_.close() if @curl_?
|
||||
@curl_ = null
|
||||
@body = null
|
||||
delete CurlBuilder.curls[@id]
|
||||
@log "closed."
|
||||
|
||||
curl.close = ->
|
||||
@end()
|
||||
|
||||
curl.open = ->
|
||||
unless curl.id?
|
||||
curl.id = ++CurlBuilder.id
|
||||
@log "opening."
|
||||
@curl_ = new Curl()
|
||||
@curl_.options = {}
|
||||
@defaultOptions = defaultOptions ? {}
|
||||
CurlBuilder.curls[curl.id] = curl
|
||||
@log "opened."
|
||||
|
||||
curl.reset = ->
|
||||
@log 'reset'
|
||||
if @curl_
|
||||
@end()
|
||||
@open()
|
||||
|
||||
curl.create = (defaultOptions) ->
|
||||
CurlBuilder.create(defaultOptions)
|
||||
|
||||
curl.get_count = ->
|
||||
Curl.get_count()
|
||||
|
||||
curl.open()
|
||||
curl
|
||||
|
||||
process.on 'exit', ->
|
||||
CurlBuilder.close_all()
|
||||
|
||||
module.exports = CurlBuilder
|
||||
|
||||
# vim: sw=2 ts=2 sts=2 expandtab :
|
155
lib/curl.js
155
lib/curl.js
|
@ -1,155 +0,0 @@
|
|||
// Generated by ToffeeScript 1.1.4-4
|
||||
(function() {
|
||||
var Curl, curl, curl_id, curls,
|
||||
__slice = [].slice,
|
||||
__hasProp = {}.hasOwnProperty;
|
||||
|
||||
try {
|
||||
Curl = require(__dirname + '/../build/Release/node-curl').Curl;
|
||||
} catch (e) {
|
||||
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.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());
|
||||
} else {
|
||||
throw new Error("unsupported option " + option);
|
||||
}
|
||||
};
|
||||
|
||||
Curl.prototype.getinfo = function(oinfo) {
|
||||
var info, info_id;
|
||||
info = oinfo.toUpperCase();
|
||||
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("unsupported info " + oinfo);
|
||||
}
|
||||
};
|
||||
|
||||
Curl.prototype.perform = function() {
|
||||
this.perform_();
|
||||
return Curl.process();
|
||||
};
|
||||
|
||||
Curl.user_options = {
|
||||
RAW: 'RAW'
|
||||
};
|
||||
|
||||
Curl.process = function() {
|
||||
var once;
|
||||
if (Curl.in_process) return;
|
||||
return (once = function() {
|
||||
var num;
|
||||
num = Curl.process_();
|
||||
if (num > 0) {
|
||||
Curl.in_process = true;
|
||||
return setTimeout(once, 80);
|
||||
} else {
|
||||
return Curl.in_process = false;
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
curl_id = 0;
|
||||
|
||||
curls = {};
|
||||
|
||||
curl = function() {
|
||||
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');
|
||||
c.chunks = [];
|
||||
length = 0;
|
||||
for (k in options) {
|
||||
if (!__hasProp.call(options, k)) continue;
|
||||
v = options[k];
|
||||
c.setopt(k, v);
|
||||
}
|
||||
c.on_write = function(chunk) {
|
||||
c.chunks.push(chunk);
|
||||
return length += chunk.length;
|
||||
};
|
||||
c.on_end = function() {
|
||||
var chunk, data, position, res, _i, _len, _ref,
|
||||
_this = this;
|
||||
data = new Buffer(length);
|
||||
position = 0;
|
||||
_ref = c.chunks;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
chunk = _ref[_i];
|
||||
chunk.copy(data, position);
|
||||
position += chunk.length;
|
||||
}
|
||||
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) {
|
||||
if (this.curl_ == null) throw new Error('curl is closed');
|
||||
return this.curl_.getinfo(info);
|
||||
};
|
||||
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);
|
||||
c.perform();
|
||||
return c;
|
||||
};
|
||||
|
||||
curl.Curl = Curl;
|
||||
|
||||
curl.get_count = function() {
|
||||
return Curl.get_count();
|
||||
};
|
||||
|
||||
module.exports = curl;
|
||||
|
||||
}).call(this);
|
129
lib/curl.toffee
129
lib/curl.toffee
|
@ -1,129 +0,0 @@
|
|||
try
|
||||
{Curl} = require __dirname + '/../build/Release/node-curl'
|
||||
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()
|
||||
|
||||
# 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()
|
||||
else
|
||||
throw new Error("unsupported option #{option}")
|
||||
|
||||
Curl::getinfo = (oinfo) ->
|
||||
info = oinfo.toUpperCase()
|
||||
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("unsupported info #{oinfo}")
|
||||
|
||||
Curl::perform = ->
|
||||
@perform_()
|
||||
Curl.process()
|
||||
|
||||
Curl.user_options =
|
||||
RAW: 'RAW'
|
||||
|
||||
Curl.process = ->
|
||||
if Curl.in_process
|
||||
return
|
||||
do once = ->
|
||||
num = Curl.process_()
|
||||
if num > 0
|
||||
Curl.in_process = true
|
||||
setTimeout once, 80
|
||||
else
|
||||
Curl.in_process = false
|
||||
|
||||
# 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'
|
||||
c.chunks = []
|
||||
length = 0
|
||||
|
||||
for own k, v of options
|
||||
c.setopt k, v
|
||||
|
||||
c.on_write = (chunk) ->
|
||||
c.chunks.push chunk
|
||||
length += chunk.length
|
||||
|
||||
c.on_end = ->
|
||||
data = new Buffer(length)
|
||||
position = 0
|
||||
for chunk in c.chunks
|
||||
chunk.copy data, position
|
||||
position += chunk.length
|
||||
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]
|
||||
|
||||
if c.options.RAW
|
||||
res.body = data
|
||||
else
|
||||
res.body = data.toString() #.toString()
|
||||
res.status = res.code = c.getinfo('RESPONSE_CODE')
|
||||
|
||||
res.info = (info)->
|
||||
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
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "node-curl",
|
||||
"version": "0.1.0",
|
||||
"version": "0.3.3",
|
||||
"author" : "Jiang Miao <jiangfriend@gmail.com>",
|
||||
"description": "node wrapper for multi curl, full implemented.",
|
||||
"description": "node wrapper for multi curl, fully implemented.",
|
||||
"keywords" : ["node-curl", "curl", "multi-curl", "mcurl"],
|
||||
"homepage": "http://github.com/jiangmiao/node-curl",
|
||||
"repository" : {
|
||||
|
@ -10,8 +10,8 @@
|
|||
"url" : "git://github.com/jiangmiao/node-curl.git"
|
||||
},
|
||||
"main" : "./lib",
|
||||
"scripts" : {
|
||||
"install" : "node-waf configure build || true"
|
||||
"scripts" : {
|
||||
"install" : "sh src/generate_curl_options_list.sh && (node-gyp rebuild || node-waf configure build)"
|
||||
},
|
||||
"engines" : { "node": ">= 0.6.0" }
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
// generated by generate_curl_options_list.sh at Mon, 13 Feb 2012 21:40:10 +0800
|
||||
CurlOption double_infos[] = {
|
||||
{"TOTAL_TIME", CURLINFO_TOTAL_TIME},
|
||||
{"NAMELOOKUP_TIME", CURLINFO_NAMELOOKUP_TIME},
|
||||
{"CONNECT_TIME", CURLINFO_CONNECT_TIME},
|
||||
{"PRETRANSFER_TIME", CURLINFO_PRETRANSFER_TIME},
|
||||
{"SIZE_UPLOAD", CURLINFO_SIZE_UPLOAD},
|
||||
{"SIZE_DOWNLOAD", CURLINFO_SIZE_DOWNLOAD},
|
||||
{"SPEED_DOWNLOAD", CURLINFO_SPEED_DOWNLOAD},
|
||||
{"SPEED_UPLOAD", CURLINFO_SPEED_UPLOAD},
|
||||
{"CONTENT_LENGTH_DOWNLOAD", CURLINFO_CONTENT_LENGTH_DOWNLOAD},
|
||||
{"CONTENT_LENGTH_UPLOAD", CURLINFO_CONTENT_LENGTH_UPLOAD},
|
||||
{"STARTTRANSFER_TIME", CURLINFO_STARTTRANSFER_TIME},
|
||||
{"REDIRECT_TIME", CURLINFO_REDIRECT_TIME},
|
||||
{"APPCONNECT_TIME", CURLINFO_APPCONNECT_TIME},
|
||||
};
|
26
src/generate_curl_options_list.sh
Normal file → Executable file
26
src/generate_curl_options_list.sh
Normal file → Executable file
|
@ -1,18 +1,36 @@
|
|||
#!/bin/sh
|
||||
|
||||
root=`dirname $0`
|
||||
|
||||
if [ "$NODE_CURL_H" != "" ] ; then
|
||||
curl_header=$NODE_CURL_H
|
||||
elif [ -f "/usr/local/include/curl/curl.h" ] ; then
|
||||
curl_header="/usr/local/include/curl/curl.h"
|
||||
elif [ -f "/usr/include/curl/curl.h" ] ; then
|
||||
curl_header="/usr/include/curl/curl.h"
|
||||
fi
|
||||
|
||||
if [ ! -f $curl_header ] ; then
|
||||
echo "cannot find curl's header file $curl_header"
|
||||
exit 1
|
||||
else
|
||||
echo "extract constants from $curl_header"
|
||||
fi
|
||||
|
||||
generate() {
|
||||
name=$1
|
||||
pattern=$2
|
||||
prefix=$3
|
||||
echo "generate $root/$name.h"
|
||||
(
|
||||
echo "// generated by $0 at $(date -R)"
|
||||
echo "// generated by $0 at $(date)"
|
||||
echo "CurlOption $name[] = {"
|
||||
cat /usr/include/curl/curl.h|perl -ne "/$pattern/i && print \"\t{\\\"\$1\\\", CURL${prefix}_\$1},\n\""
|
||||
cat "$curl_header"|perl -ne "/$pattern/i && print \"\t{\\\"\$1\\\", CURL${prefix}_\$1},\n\""
|
||||
echo '};'
|
||||
) > $name.h
|
||||
) > $root/$name.h
|
||||
}
|
||||
generate integer_options 'CINIT\((\w+).*LONG' OPT
|
||||
generate string_options 'CINIT\((\w+).*OBJECT' OPT
|
||||
generate string_options 'CINIT\((\w+).*(STRINGPOINT|OBJECT)' OPT
|
||||
|
||||
generate integer_infos 'CURLINFO_(\w+).*LONG' INFO
|
||||
generate string_infos 'CURLINFO_(\w+).*STRING' INFO
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
// generated by generate_curl_options_list.sh at Mon, 13 Feb 2012 21:40:10 +0800
|
||||
CurlOption integer_infos[] = {
|
||||
{"RESPONSE_CODE", CURLINFO_RESPONSE_CODE},
|
||||
{"HEADER_SIZE", CURLINFO_HEADER_SIZE},
|
||||
{"REQUEST_SIZE", CURLINFO_REQUEST_SIZE},
|
||||
{"SSL_VERIFYRESULT", CURLINFO_SSL_VERIFYRESULT},
|
||||
{"FILETIME", CURLINFO_FILETIME},
|
||||
{"REDIRECT_COUNT", CURLINFO_REDIRECT_COUNT},
|
||||
{"HTTP_CONNECTCODE", CURLINFO_HTTP_CONNECTCODE},
|
||||
{"HTTPAUTH_AVAIL", CURLINFO_HTTPAUTH_AVAIL},
|
||||
{"PROXYAUTH_AVAIL", CURLINFO_PROXYAUTH_AVAIL},
|
||||
{"OS_ERRNO", CURLINFO_OS_ERRNO},
|
||||
{"NUM_CONNECTS", CURLINFO_NUM_CONNECTS},
|
||||
{"LASTSOCKET", CURLINFO_LASTSOCKET},
|
||||
{"CONDITION_UNMET", CURLINFO_CONDITION_UNMET},
|
||||
{"RTSP_CLIENT_CSEQ", CURLINFO_RTSP_CLIENT_CSEQ},
|
||||
{"RTSP_SERVER_CSEQ", CURLINFO_RTSP_SERVER_CSEQ},
|
||||
{"RTSP_CSEQ_RECV", CURLINFO_RTSP_CSEQ_RECV},
|
||||
{"PRIMARY_PORT", CURLINFO_PRIMARY_PORT},
|
||||
{"LOCAL_PORT", CURLINFO_LOCAL_PORT},
|
||||
};
|
|
@ -1,91 +0,0 @@
|
|||
// generated by generate_curl_options_list.sh at Mon, 13 Feb 2012 21:40:10 +0800
|
||||
CurlOption integer_options[] = {
|
||||
{"PORT", CURLOPT_PORT},
|
||||
{"TIMEOUT", CURLOPT_TIMEOUT},
|
||||
{"INFILESIZE", CURLOPT_INFILESIZE},
|
||||
{"LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT},
|
||||
{"LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME},
|
||||
{"RESUME_FROM", CURLOPT_RESUME_FROM},
|
||||
{"CRLF", CURLOPT_CRLF},
|
||||
{"SSLVERSION", CURLOPT_SSLVERSION},
|
||||
{"TIMECONDITION", CURLOPT_TIMECONDITION},
|
||||
{"TIMEVALUE", CURLOPT_TIMEVALUE},
|
||||
{"VERBOSE", CURLOPT_VERBOSE},
|
||||
{"HEADER", CURLOPT_HEADER},
|
||||
{"NOPROGRESS", CURLOPT_NOPROGRESS},
|
||||
{"NOBODY", CURLOPT_NOBODY},
|
||||
{"FAILONERROR", CURLOPT_FAILONERROR},
|
||||
{"UPLOAD", CURLOPT_UPLOAD},
|
||||
{"POST", CURLOPT_POST},
|
||||
{"DIRLISTONLY", CURLOPT_DIRLISTONLY},
|
||||
{"APPEND", CURLOPT_APPEND},
|
||||
{"NETRC", CURLOPT_NETRC},
|
||||
{"FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION},
|
||||
{"TRANSFERTEXT", CURLOPT_TRANSFERTEXT},
|
||||
{"PUT", CURLOPT_PUT},
|
||||
{"AUTOREFERER", CURLOPT_AUTOREFERER},
|
||||
{"PROXYPORT", CURLOPT_PROXYPORT},
|
||||
{"POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE},
|
||||
{"HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL},
|
||||
{"SSL_VERIFYPEER", CURLOPT_SSL_VERIFYPEER},
|
||||
{"MAXREDIRS", CURLOPT_MAXREDIRS},
|
||||
{"FILETIME", CURLOPT_FILETIME},
|
||||
{"MAXCONNECTS", CURLOPT_MAXCONNECTS},
|
||||
{"CLOSEPOLICY", CURLOPT_CLOSEPOLICY},
|
||||
{"FRESH_CONNECT", CURLOPT_FRESH_CONNECT},
|
||||
{"FORBID_REUSE", CURLOPT_FORBID_REUSE},
|
||||
{"CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT},
|
||||
{"HTTPGET", CURLOPT_HTTPGET},
|
||||
{"SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST},
|
||||
{"HTTP_VERSION", CURLOPT_HTTP_VERSION},
|
||||
{"FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV},
|
||||
{"SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT},
|
||||
{"DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE},
|
||||
{"DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT},
|
||||
{"COOKIESESSION", CURLOPT_COOKIESESSION},
|
||||
{"BUFFERSIZE", CURLOPT_BUFFERSIZE},
|
||||
{"NOSIGNAL", CURLOPT_NOSIGNAL},
|
||||
{"PROXYTYPE", CURLOPT_PROXYTYPE},
|
||||
{"UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH},
|
||||
{"FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT},
|
||||
{"HTTPAUTH", CURLOPT_HTTPAUTH},
|
||||
{"FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS},
|
||||
{"PROXYAUTH", CURLOPT_PROXYAUTH},
|
||||
{"FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT},
|
||||
{"IPRESOLVE", CURLOPT_IPRESOLVE},
|
||||
{"MAXFILESIZE", CURLOPT_MAXFILESIZE},
|
||||
{"USE_SSL", CURLOPT_USE_SSL},
|
||||
{"TCP_NODELAY", CURLOPT_TCP_NODELAY},
|
||||
{"FTPSSLAUTH", CURLOPT_FTPSSLAUTH},
|
||||
{"IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH},
|
||||
{"FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP},
|
||||
{"FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD},
|
||||
{"LOCALPORT", CURLOPT_LOCALPORT},
|
||||
{"LOCALPORTRANGE", CURLOPT_LOCALPORTRANGE},
|
||||
{"CONNECT_ONLY", CURLOPT_CONNECT_ONLY},
|
||||
{"SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE},
|
||||
{"SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES},
|
||||
{"FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC},
|
||||
{"TIMEOUT_MS", CURLOPT_TIMEOUT_MS},
|
||||
{"CONNECTTIMEOUT_MS", CURLOPT_CONNECTTIMEOUT_MS},
|
||||
{"HTTP_TRANSFER_DECODING", CURLOPT_HTTP_TRANSFER_DECODING},
|
||||
{"HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING},
|
||||
{"NEW_FILE_PERMS", CURLOPT_NEW_FILE_PERMS},
|
||||
{"NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS},
|
||||
{"POSTREDIR", CURLOPT_POSTREDIR},
|
||||
{"PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE},
|
||||
{"ADDRESS_SCOPE", CURLOPT_ADDRESS_SCOPE},
|
||||
{"CERTINFO", CURLOPT_CERTINFO},
|
||||
{"TFTP_BLKSIZE", CURLOPT_TFTP_BLKSIZE},
|
||||
{"SOCKS5_GSSAPI_NEC", CURLOPT_SOCKS5_GSSAPI_NEC},
|
||||
{"PROTOCOLS", CURLOPT_PROTOCOLS},
|
||||
{"REDIR_PROTOCOLS", CURLOPT_REDIR_PROTOCOLS},
|
||||
{"FTP_USE_PRET", CURLOPT_FTP_USE_PRET},
|
||||
{"RTSP_REQUEST", CURLOPT_RTSP_REQUEST},
|
||||
{"RTSP_CLIENT_CSEQ", CURLOPT_RTSP_CLIENT_CSEQ},
|
||||
{"RTSP_SERVER_CSEQ", CURLOPT_RTSP_SERVER_CSEQ},
|
||||
{"WILDCARDMATCH", CURLOPT_WILDCARDMATCH},
|
||||
{"TRANSFER_ENCODING", CURLOPT_TRANSFER_ENCODING},
|
||||
{"GSSAPI_DELEGATION", CURLOPT_GSSAPI_DELEGATION},
|
||||
{"ACCEPTTIMEOUT_MS", CURLOPT_ACCEPTTIMEOUT_MS},
|
||||
};
|
|
@ -5,3 +5,7 @@ void init(v8::Handle<v8::Object> target)
|
|||
{
|
||||
NodeCurl::Initialize(target);
|
||||
}
|
||||
|
||||
#ifdef NODE_MODULE
|
||||
NODE_MODULE(node_curl, init)
|
||||
#endif
|
||||
|
|
246
src/node-curl.h
246
src/node-curl.h
|
@ -1,20 +1,102 @@
|
|||
#ifndef NODE_CURL_NOHE_CURL_H
|
||||
#define NODE_CURL_NOHE_CURL_H
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <v8.h>
|
||||
#include <node.h>
|
||||
#include <node_buffer.h>
|
||||
#include <curl/curl.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NODE_CURL_EXPORT(name) export_curl_options(t, #name, name, sizeof(name) / sizeof(CurlOption));
|
||||
|
||||
class NodeCurlHttppost
|
||||
{
|
||||
public:
|
||||
curl_httppost *first;
|
||||
curl_httppost *last;
|
||||
|
||||
public:
|
||||
NodeCurlHttppost()
|
||||
: first(NULL), last(NULL)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
~NodeCurlHttppost()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
curl_httppost *cur = first;
|
||||
while (cur) {
|
||||
curl_httppost *next = cur->next;
|
||||
if (cur->contenttype)
|
||||
free(cur->contenttype);
|
||||
if (cur->contents)
|
||||
free(cur->contents);
|
||||
if (cur->buffer)
|
||||
free(cur->buffer);
|
||||
if (cur->name)
|
||||
free(cur->name);
|
||||
free(cur);
|
||||
cur = next;
|
||||
}
|
||||
first = NULL;
|
||||
last = NULL;
|
||||
}
|
||||
|
||||
void append()
|
||||
{
|
||||
if (!first) {
|
||||
first = (curl_httppost*)calloc(1, sizeof(curl_httppost));
|
||||
last = first;
|
||||
} else {
|
||||
last->next = (curl_httppost*)calloc(1, sizeof(curl_httppost));
|
||||
last = last->next;
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
NAME,
|
||||
FILE,
|
||||
CONTENTS,
|
||||
TYPE
|
||||
};
|
||||
|
||||
void set(int field, char *value, long length)
|
||||
{
|
||||
value = strndup(value, length);
|
||||
switch (field) {
|
||||
case NAME:
|
||||
last->name = value;
|
||||
last->namelength = length;
|
||||
break;
|
||||
case TYPE:
|
||||
last->contenttype = value;
|
||||
break;
|
||||
case FILE:
|
||||
last->flags |= CURL_HTTPPOST_FILENAME;
|
||||
case CONTENTS:
|
||||
last->contents = value;
|
||||
last->contentslength = length;
|
||||
break;
|
||||
default:
|
||||
// `default` should never be reached.
|
||||
free(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class NodeCurl
|
||||
{
|
||||
struct CurlOption
|
||||
struct CurlOption
|
||||
{
|
||||
const char *name;
|
||||
int value;
|
||||
|
@ -25,11 +107,15 @@ class NodeCurl
|
|||
static bool is_ref;
|
||||
static std::map< CURL*, NodeCurl* > curls;
|
||||
static int count;
|
||||
static int transfered;
|
||||
|
||||
CURL * curl;
|
||||
v8::Persistent<v8::Object> handle;
|
||||
|
||||
bool in_curlm;
|
||||
std::vector<curl_slist*> slists;
|
||||
std::map<int, std::string> strings;
|
||||
NodeCurlHttppost httppost;
|
||||
|
||||
NodeCurl(v8::Handle<v8::Object> object)
|
||||
: in_curlm(false)
|
||||
|
@ -48,6 +134,8 @@ class NodeCurl
|
|||
}
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_function);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
|
||||
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_function);
|
||||
curl_easy_setopt(curl, CURLOPT_HEADERDATA, this);
|
||||
curls[curl] = this;
|
||||
}
|
||||
|
||||
|
@ -104,10 +192,18 @@ class NodeCurl
|
|||
// curl write function mapping
|
||||
static size_t write_function(char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||
{
|
||||
transfered += size * nmemb;
|
||||
NodeCurl *nodecurl = (NodeCurl*)userdata;
|
||||
return nodecurl->on_write(ptr, size * nmemb);
|
||||
}
|
||||
|
||||
static size_t header_function(char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||
{
|
||||
transfered += size * nmemb;
|
||||
NodeCurl *nodecurl = (NodeCurl*)userdata;
|
||||
return nodecurl->on_header(ptr, size * nmemb);
|
||||
}
|
||||
|
||||
size_t on_write(char *data, size_t n)
|
||||
{
|
||||
static v8::Persistent<v8::String> SYM_ON_WRITE = v8::Persistent<v8::String>::New(v8::String::NewSymbol("on_write"));
|
||||
|
@ -116,7 +212,28 @@ class NodeCurl
|
|||
{
|
||||
node::Buffer * buffer = node::Buffer::New(data, n);
|
||||
v8::Handle<v8::Value> argv[] = { buffer->handle_ };
|
||||
cb->ToObject()->CallAsFunction(handle, 1, argv);
|
||||
v8::Handle<v8::Value> rt = cb->ToObject()->CallAsFunction(handle, 1, argv);
|
||||
if (rt.IsEmpty())
|
||||
return 0;
|
||||
else
|
||||
return rt->Int32Value();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t on_header(char *data, size_t n)
|
||||
{
|
||||
static v8::Persistent<v8::String> SYM_ON_HEADER = v8::Persistent<v8::String>::New(v8::String::NewSymbol("on_header"));
|
||||
v8::Handle<v8::Value> cb = handle->Get(SYM_ON_HEADER);
|
||||
if (cb->IsFunction())
|
||||
{
|
||||
node::Buffer * buffer = node::Buffer::New(data, n);
|
||||
v8::Handle<v8::Value> argv[] = { buffer->handle_ };
|
||||
v8::Handle<v8::Value> rt = cb->ToObject()->CallAsFunction(handle, 1, argv);
|
||||
if (rt.IsEmpty())
|
||||
return 0;
|
||||
else
|
||||
return rt->Int32Value();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
@ -155,12 +272,12 @@ class NodeCurl
|
|||
{
|
||||
return raise("curl_easy_getinfo failed", curl_easy_strerror(code));
|
||||
}
|
||||
return JsClass::New(result);
|
||||
return result ? JsClass::New(result) : v8::Null();
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> getinfo_int(const v8::Arguments & args)
|
||||
{
|
||||
return getinfo<int, v8::Integer>(args);
|
||||
return getinfo<long, v8::Integer>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> getinfo_str(const v8::Arguments & args)
|
||||
|
@ -189,7 +306,7 @@ class NodeCurl
|
|||
cur = slist;
|
||||
while (cur)
|
||||
{
|
||||
array->Set(array->Length(), v8::String::New(slist->data));
|
||||
array->Set(array->Length(), v8::String::New(cur->data));
|
||||
cur = cur->next;
|
||||
}
|
||||
curl_slist_free_all(slist);
|
||||
|
@ -204,7 +321,7 @@ class NodeCurl
|
|||
return v8::Integer::New(
|
||||
curl_easy_setopt(
|
||||
curl,
|
||||
(CURLoption)option->Int32Value(),
|
||||
(CURLoption)option->Int32Value(),
|
||||
value
|
||||
)
|
||||
);
|
||||
|
@ -217,7 +334,14 @@ class NodeCurl
|
|||
|
||||
static v8::Handle<v8::Value> setopt_str(const v8::Arguments & args)
|
||||
{
|
||||
return unwrap(args.This())->setopt(args[0], *v8::String::Utf8Value(args[1]) );
|
||||
// Create a string copy
|
||||
// https://github.com/jiangmiao/node-curl/issues/3
|
||||
NodeCurl * node_curl = unwrap(args.This());
|
||||
int key = args[0]->Int32Value();
|
||||
v8::String::Utf8Value value(args[1]);
|
||||
int length = value.length();
|
||||
node_curl->strings[key] = std::string(*value, length);
|
||||
return unwrap(args.This())->setopt(args[0], node_curl->strings[key].c_str() );
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> setopt_slist(const v8::Arguments & args)
|
||||
|
@ -228,6 +352,30 @@ class NodeCurl
|
|||
return node_curl->setopt(args[0], slist);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> setopt_httppost(const v8::Arguments & args)
|
||||
{
|
||||
NodeCurl * node_curl = unwrap(args.This());
|
||||
NodeCurlHttppost &httppost = node_curl->httppost;
|
||||
v8::Handle<v8::Array> rows = v8::Handle<v8::Array>::Cast(args[0]);
|
||||
httppost.reset();
|
||||
for (uint32_t i=0, len = rows->Length(); i<len; ++i)
|
||||
{
|
||||
v8::Handle<v8::Array> cols = v8::Handle<v8::Array>::Cast(rows->Get(i));
|
||||
uint32_t j=0, cols_len = cols->Length();
|
||||
httppost.append();
|
||||
while (j<cols_len)
|
||||
{
|
||||
int field = cols->Get(j++)->Int32Value();
|
||||
v8::Handle<v8::Object> buffer = cols->Get(j++)->ToObject();
|
||||
char *value = node::Buffer::Data(buffer);
|
||||
int length = node::Buffer::Length(buffer);
|
||||
httppost.set(field, value, length);
|
||||
}
|
||||
}
|
||||
curl_easy_setopt(node_curl->curl, CURLOPT_HTTPPOST, node_curl->httppost.first);
|
||||
return args.This();
|
||||
}
|
||||
|
||||
static curl_slist * value_to_slist(v8::Handle<v8::Value> value)
|
||||
{
|
||||
curl_slist * slist = NULL;
|
||||
|
@ -284,32 +432,11 @@ class NodeCurl
|
|||
// int process()
|
||||
static v8::Handle<v8::Value> process(const v8::Arguments & args)
|
||||
{
|
||||
transfered = 0;
|
||||
if (running_handles > 0)
|
||||
{
|
||||
CURLMcode code;
|
||||
int max_fd = FD_SETSIZE;
|
||||
fd_set read_fds;
|
||||
fd_set write_fds;
|
||||
fd_set error_fds;
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&write_fds);
|
||||
FD_ZERO(&error_fds);
|
||||
// use select because of libuv didn't support sockfd well
|
||||
code = curl_multi_fdset(curlm, &read_fds, &write_fds, &error_fds, &max_fd);
|
||||
if (code != CURLM_OK)
|
||||
{
|
||||
return raise("curl_multi_fdset failed", curl_multi_strerror(code));
|
||||
}
|
||||
if (max_fd > 0)
|
||||
{
|
||||
timeval tv = {0};
|
||||
int n = select(max_fd+1, &read_fds, &write_fds, &error_fds, &tv);
|
||||
if (n == 0)
|
||||
{
|
||||
return v8::Integer::New(running_handles);
|
||||
}
|
||||
}
|
||||
|
||||
// remove select totally for timeout doesn't work properly
|
||||
do
|
||||
{
|
||||
code = curl_multi_perform(curlm, &running_handles);
|
||||
|
@ -327,35 +454,42 @@ class NodeCurl
|
|||
if (msg->msg == CURLMSG_DONE)
|
||||
{
|
||||
NodeCurl * curl = curls[msg->easy_handle];
|
||||
// ensure curl still exists,
|
||||
// gc will delete the curl if there is no reference.
|
||||
if (msg->data.result == CURLE_OK)
|
||||
curl->on_end(msg);
|
||||
else
|
||||
curl->on_error(msg);
|
||||
CURLMsg msg_copy = *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));
|
||||
}
|
||||
|
||||
if (msg_copy.data.result == CURLE_OK)
|
||||
curl->on_end(&msg_copy);
|
||||
else
|
||||
curl->on_error(&msg_copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
return v8::Integer::New(running_handles);
|
||||
return v8::Integer::New(transfered + (int)(running_handles > 0));
|
||||
}
|
||||
|
||||
// perform()
|
||||
static v8::Handle<v8::Value> perform(const v8::Arguments & args)
|
||||
{
|
||||
NodeCurl *curl = unwrap(args.This());
|
||||
if (!curl)
|
||||
return raise("curl is closed.");
|
||||
|
||||
if (curl->in_curlm)
|
||||
return raise("curl session is running.");
|
||||
|
||||
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));
|
||||
}
|
||||
curl->in_curlm = true;
|
||||
++running_handles;
|
||||
|
||||
return args.This();
|
||||
}
|
||||
|
||||
|
@ -389,18 +523,19 @@ class NodeCurl
|
|||
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 , "setopt_httppost_" , setopt_httppost);
|
||||
|
||||
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_PROTOTYPE_METHOD(t, "close_", close);
|
||||
|
||||
NODE_SET_METHOD(t , "process_" , process);
|
||||
NODE_SET_METHOD(t , "get_count" , get_count);
|
||||
|
||||
// Set curl constants
|
||||
// Set curl constants
|
||||
#include "string_options.h"
|
||||
#include "integer_options.h"
|
||||
#include "string_infos.h"
|
||||
|
@ -409,13 +544,22 @@ class NodeCurl
|
|||
|
||||
#define X(name) {#name, CURLOPT_##name}
|
||||
CurlOption slist_options[] = {
|
||||
#if LIBCURL_VERSION_NUM >= 0x070a03
|
||||
X(HTTP200ALIASES),
|
||||
#endif
|
||||
|
||||
#if LIBCURL_VERSION_NUM >= 0x071400
|
||||
X(MAIL_RCPT),
|
||||
#endif
|
||||
|
||||
#if LIBCURL_VERSION_NUM >= 0x071503
|
||||
X(RESOLVE),
|
||||
#endif
|
||||
|
||||
X(HTTPHEADER),
|
||||
X(HTTP200ALIASES),
|
||||
X(MAIL_RCPT),
|
||||
X(QUOTE),
|
||||
X(POSTQUOTE),
|
||||
X(PREQUOTE),
|
||||
X(RESOLVE),
|
||||
X(TELNETOPTIONS)
|
||||
};
|
||||
#undef X
|
||||
|
@ -425,6 +569,15 @@ class NodeCurl
|
|||
X(SSL_ENGINES),
|
||||
X(COOKIELIST)
|
||||
};
|
||||
|
||||
#undef X
|
||||
#define X(name) {#name, NodeCurlHttppost::name}
|
||||
CurlOption httppost_options[] = {
|
||||
X(NAME),
|
||||
X(FILE),
|
||||
X(CONTENTS),
|
||||
X(TYPE)
|
||||
};
|
||||
#undef X
|
||||
|
||||
NODE_CURL_EXPORT(string_options);
|
||||
|
@ -436,6 +589,8 @@ class NodeCurl
|
|||
NODE_CURL_EXPORT(double_infos);
|
||||
NODE_CURL_EXPORT(slist_infos);
|
||||
|
||||
NODE_CURL_EXPORT(httppost_options);
|
||||
|
||||
target->Set(v8::String::NewSymbol("Curl"), t->GetFunction());
|
||||
return target;
|
||||
}
|
||||
|
@ -446,5 +601,6 @@ int NodeCurl::running_handles = 0;
|
|||
bool NodeCurl::is_ref = false;
|
||||
std::map< CURL*, NodeCurl* > NodeCurl::curls;
|
||||
int NodeCurl::count = 0;
|
||||
int NodeCurl::transfered = 0;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
// generated by generate_curl_options_list.sh at Mon, 13 Feb 2012 21:40:10 +0800
|
||||
CurlOption string_infos[] = {
|
||||
{"EFFECTIVE_URL", CURLINFO_EFFECTIVE_URL},
|
||||
{"CONTENT_TYPE", CURLINFO_CONTENT_TYPE},
|
||||
{"PRIVATE", CURLINFO_PRIVATE},
|
||||
{"FTP_ENTRY_PATH", CURLINFO_FTP_ENTRY_PATH},
|
||||
{"REDIRECT_URL", CURLINFO_REDIRECT_URL},
|
||||
{"PRIMARY_IP", CURLINFO_PRIMARY_IP},
|
||||
{"RTSP_SESSION_ID", CURLINFO_RTSP_SESSION_ID},
|
||||
{"LOCAL_IP", CURLINFO_LOCAL_IP},
|
||||
};
|
|
@ -1,84 +0,0 @@
|
|||
// generated by generate_curl_options_list.sh at Mon, 13 Feb 2012 21:40:10 +0800
|
||||
CurlOption string_options[] = {
|
||||
{"FILE", CURLOPT_FILE},
|
||||
{"URL", CURLOPT_URL},
|
||||
{"PROXY", CURLOPT_PROXY},
|
||||
{"USERPWD", CURLOPT_USERPWD},
|
||||
{"PROXYUSERPWD", CURLOPT_PROXYUSERPWD},
|
||||
{"RANGE", CURLOPT_RANGE},
|
||||
{"INFILE", CURLOPT_INFILE},
|
||||
{"ERRORBUFFER", CURLOPT_ERRORBUFFER},
|
||||
{"POSTFIELDS", CURLOPT_POSTFIELDS},
|
||||
{"REFERER", CURLOPT_REFERER},
|
||||
{"FTPPORT", CURLOPT_FTPPORT},
|
||||
{"USERAGENT", CURLOPT_USERAGENT},
|
||||
{"COOKIE", CURLOPT_COOKIE},
|
||||
{"HTTPHEADER", CURLOPT_HTTPHEADER},
|
||||
{"HTTPPOST", CURLOPT_HTTPPOST},
|
||||
{"SSLCERT", CURLOPT_SSLCERT},
|
||||
{"KEYPASSWD", CURLOPT_KEYPASSWD},
|
||||
{"QUOTE", CURLOPT_QUOTE},
|
||||
{"WRITEHEADER", CURLOPT_WRITEHEADER},
|
||||
{"COOKIEFILE", CURLOPT_COOKIEFILE},
|
||||
{"CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST},
|
||||
{"STDERR", CURLOPT_STDERR},
|
||||
{"POSTQUOTE", CURLOPT_POSTQUOTE},
|
||||
{"WRITEINFO", CURLOPT_WRITEINFO},
|
||||
{"PROGRESSDATA", CURLOPT_PROGRESSDATA},
|
||||
{"INTERFACE", CURLOPT_INTERFACE},
|
||||
{"KRBLEVEL", CURLOPT_KRBLEVEL},
|
||||
{"CAINFO", CURLOPT_CAINFO},
|
||||
{"TELNETOPTIONS", CURLOPT_TELNETOPTIONS},
|
||||
{"RANDOM_FILE", CURLOPT_RANDOM_FILE},
|
||||
{"EGDSOCKET", CURLOPT_EGDSOCKET},
|
||||
{"COOKIEJAR", CURLOPT_COOKIEJAR},
|
||||
{"SSL_CIPHER_LIST", CURLOPT_SSL_CIPHER_LIST},
|
||||
{"SSLCERTTYPE", CURLOPT_SSLCERTTYPE},
|
||||
{"SSLKEY", CURLOPT_SSLKEY},
|
||||
{"SSLKEYTYPE", CURLOPT_SSLKEYTYPE},
|
||||
{"SSLENGINE", CURLOPT_SSLENGINE},
|
||||
{"PREQUOTE", CURLOPT_PREQUOTE},
|
||||
{"DEBUGDATA", CURLOPT_DEBUGDATA},
|
||||
{"CAPATH", CURLOPT_CAPATH},
|
||||
{"SHARE", CURLOPT_SHARE},
|
||||
{"ACCEPT_ENCODING", CURLOPT_ACCEPT_ENCODING},
|
||||
{"PRIVATE", CURLOPT_PRIVATE},
|
||||
{"HTTP200ALIASES", CURLOPT_HTTP200ALIASES},
|
||||
{"SSL_CTX_DATA", CURLOPT_SSL_CTX_DATA},
|
||||
{"NETRC_FILE", CURLOPT_NETRC_FILE},
|
||||
{"IOCTLDATA", CURLOPT_IOCTLDATA},
|
||||
{"FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT},
|
||||
{"COOKIELIST", CURLOPT_COOKIELIST},
|
||||
{"FTP_ALTERNATIVE_TO_USER", CURLOPT_FTP_ALTERNATIVE_TO_USER},
|
||||
{"SOCKOPTDATA", CURLOPT_SOCKOPTDATA},
|
||||
{"SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE},
|
||||
{"SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE},
|
||||
{"SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5},
|
||||
{"OPENSOCKETDATA", CURLOPT_OPENSOCKETDATA},
|
||||
{"COPYPOSTFIELDS", CURLOPT_COPYPOSTFIELDS},
|
||||
{"SEEKDATA", CURLOPT_SEEKDATA},
|
||||
{"CRLFILE", CURLOPT_CRLFILE},
|
||||
{"ISSUERCERT", CURLOPT_ISSUERCERT},
|
||||
{"USERNAME", CURLOPT_USERNAME},
|
||||
{"PASSWORD", CURLOPT_PASSWORD},
|
||||
{"PROXYUSERNAME", CURLOPT_PROXYUSERNAME},
|
||||
{"PROXYPASSWORD", CURLOPT_PROXYPASSWORD},
|
||||
{"NOPROXY", CURLOPT_NOPROXY},
|
||||
{"SOCKS5_GSSAPI_SERVICE", CURLOPT_SOCKS5_GSSAPI_SERVICE},
|
||||
{"SSH_KNOWNHOSTS", CURLOPT_SSH_KNOWNHOSTS},
|
||||
{"SSH_KEYDATA", CURLOPT_SSH_KEYDATA},
|
||||
{"MAIL_FROM", CURLOPT_MAIL_FROM},
|
||||
{"MAIL_RCPT", CURLOPT_MAIL_RCPT},
|
||||
{"RTSP_SESSION_ID", CURLOPT_RTSP_SESSION_ID},
|
||||
{"RTSP_STREAM_URI", CURLOPT_RTSP_STREAM_URI},
|
||||
{"RTSP_TRANSPORT", CURLOPT_RTSP_TRANSPORT},
|
||||
{"INTERLEAVEDATA", CURLOPT_INTERLEAVEDATA},
|
||||
{"CHUNK_DATA", CURLOPT_CHUNK_DATA},
|
||||
{"FNMATCH_DATA", CURLOPT_FNMATCH_DATA},
|
||||
{"RESOLVE", CURLOPT_RESOLVE},
|
||||
{"TLSAUTH_USERNAME", CURLOPT_TLSAUTH_USERNAME},
|
||||
{"TLSAUTH_PASSWORD", CURLOPT_TLSAUTH_PASSWORD},
|
||||
{"TLSAUTH_TYPE", CURLOPT_TLSAUTH_TYPE},
|
||||
{"CLOSESOCKETDATA", CURLOPT_CLOSESOCKETDATA},
|
||||
{"DNS_SERVERS", CURLOPT_DNS_SERVERS},
|
||||
};
|
2
wscript
2
wscript
|
@ -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'])
|
||||
conf.env.append_unique('CXXFLAGS', ['-Wall', '-O1', '-fno-inline-functions'])
|
||||
conf.env['LIB_CURL'] = 'curl'
|
||||
|
||||
def build(bld):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue