Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

needle

Package Overview
Dependencies
Maintainers
1
Versions
112
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

needle - npm Package Compare versions

Comparing version 0.2.9 to 0.3.0

370

lib/needle.js

@@ -26,22 +26,22 @@ //////////////////////////////////////////

var parsers = {
'application/json': function(data, callback){
callback(data && JSON.parse(data));
}
'application/json': function(data, callback){
callback(data && JSON.parse(data));
}
};
try {
var xml2js = require('xml2js');
parsers['application/xml'] = function(data, callback){
var xml2js = require('xml2js');
parsers['application/xml'] = function(data, callback){
var xml_parser = new xml2js.Parser();
var xml_parser = new xml2js.Parser();
xml_parser.on('end', callback);
xml_parser.on('error', function(result) {
throw("Error parsing XML!")
// callback(null);
});
xml_parser.on('end', callback);
xml_parser.on('error', function(result) {
throw("Error parsing XML!")
// callback(null);
});
xml_parser.parseString(data);
xml_parser.parseString(data);
};
};
} catch(e) { }

@@ -51,15 +51,15 @@

function flatten(object, into, prefix){
into = into || {};
into = into || {};
for(key in object){
var prefix_key = prefix ? prefix + "[" + key + "]" : key;
var prop = object[key];
for(key in object){
var prefix_key = prefix ? prefix + "[" + key + "]" : key;
var prop = object[key];
if(prop && typeof prop === "object" && !((prop.buffer || prop.file) && prop.content_type))
flatten(prop, into, prefix_key)
else
into[prefix_key] = prop;
}
if(prop && typeof prop === "object" && !((prop.buffer || prop.file) && prop.content_type))
flatten(prop, into, prefix_key)
else
into[prefix_key] = prop;
}
return into;
return into;
}

@@ -69,218 +69,218 @@

default_boundary: '--------------------NODENEEDLEHTTPCLIENT',
default_user_agent: default_user_agent,
default_boundary: '--------------------NODENEEDLEHTTPCLIENT',
default_user_agent: default_user_agent,
request: function(uri, method, data, options, callback){
request: function(uri, method, data, options, callback){
var self = this, post_data = null;
var callback = (typeof options == 'function') ? options : callback;
var options = options || {};
if(uri.indexOf('http') == -1) uri = 'http://' + uri;
var self = this, post_data = null;
var callback = (typeof options == 'function') ? options : callback;
var options = options || {};
if(uri.indexOf('http') == -1) uri = 'http://' + uri;
var method = options.method || 'GET';
var method = options.method || 'GET';
var config = {
base_opts: {},
proxy: options.proxy,
encoding: options.encoding || (options.multipart ? 'binary' : 'utf8'),
parse_response: options.parse === false ? false : true,
follow: options.follow === false ? 0 : options.follow || 10, // 10 by default
timeout: (typeof options.timeout == 'number') ? options.timeout : 10000
}
var config = {
base_opts: {},
proxy: options.proxy,
encoding: options.encoding || (options.multipart ? 'binary' : 'utf8'),
parse_response: options.parse === false ? false : true,
follow: options.follow === false ? 0 : options.follow || 10, // 10 by default
timeout: (typeof options.timeout == 'number') ? options.timeout : 10000
}
additional_http_opts.forEach(function(key){
if(typeof options[key] != 'undefined')
config.base_opts[key] = options[key];
});
additional_http_opts.forEach(function(key){
if(typeof options[key] != 'undefined')
config.base_opts[key] = options[key];
});
config.headers = {
"User-Agent": options.user_agent || this.default_user_agent,
"Connection": "close",
"Accept": "*/*"
}
config.headers = {
"User-Agent": options.user_agent || this.default_user_agent,
"Connection": "close",
"Accept": "*/*"
}
if (options.compressed && typeof unzip != 'undefined')
config.headers['Accept-Encoding'] = 'gzip,deflate';
if (options.compressed && typeof unzip != 'undefined')
config.headers['Accept-Encoding'] = 'gzip,deflate';
for(h in options.headers)
config.headers[h] = options.headers[h];
for(h in options.headers)
config.headers[h] = options.headers[h];
if(options.username && options.password){
var b = new Buffer([options.username, options.password].join(':'));
config.headers['Authorization'] = "Basic " + b.toString('base64');
}
if(options.username && options.password){
var b = new Buffer([options.username, options.password].join(':'));
config.headers['Authorization'] = "Basic " + b.toString('base64');
}
if(data) {
if(options.multipart){
if(data) {
if(options.multipart){
var boundary = options.boundary || this.default_boundary;
return this.build_multipart_body(data, boundary, function(err, body){
var boundary = options.boundary || this.default_boundary;
return this.build_multipart_body(data, boundary, function(err, body){
if(err) throw(err);
config.headers['Content-Type'] = 'multipart/form-data; boundary=' + boundary;
config.headers['Content-Length'] = body.length;
self.send_request(1, method, uri, config, body, callback);
if(err) throw(err);
config.headers['Content-Type'] = 'multipart/form-data; boundary=' + boundary;
config.headers['Content-Length'] = body.length;
self.send_request(1, method, uri, config, body, callback);
});
});
} else {
post_data = (typeof(data) === "string") ? data : stringify(data);
config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
config.headers['Content-Length'] = post_data.length;
}
} else {
post_data = (typeof(data) === "string") ? data : stringify(data);
config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
config.headers['Content-Length'] = post_data.length;
}
}
}
this.send_request(1, method, uri, config, post_data, callback);
this.send_request(1, method, uri, config, post_data, callback);
},
},
get_request_opts: function(method, uri, config){
get_request_opts: function(method, uri, config){
var opts = config.base_opts, proxy = config.proxy;
var remote = proxy ? url.parse(proxy) : url.parse(uri);
var opts = config.base_opts, proxy = config.proxy;
var remote = proxy ? url.parse(proxy) : url.parse(uri);
opts.host = remote.hostname;
opts.port = remote.port || (remote.protocol == 'https:' ? 443 : 80);
opts.protocol = remote.protocol;
opts.path = proxy ? uri : remote.pathname + (remote.search || '');
opts.method = method;
opts.headers = config.headers;
opts.headers["Host"] = proxy ? url.parse(uri).hostname : remote.hostname;
opts.host = remote.hostname;
opts.port = remote.port || (remote.protocol == 'https:' ? 443 : 80);
opts.protocol = remote.protocol;
opts.path = proxy ? uri : remote.pathname + (remote.search || '');
opts.method = method;
opts.headers = config.headers;
opts.headers["Host"] = proxy ? url.parse(uri).hostname : remote.hostname;
return opts;
},
return opts;
},
send_request: function(count, method, uri, config, post_data, callback){
send_request: function(count, method, uri, config, post_data, callback){
var self = this, timer, response_opts = {parse_response: config.parse_response};
var request_opts = this.get_request_opts(method, uri, config);
var self = this, timer, response_opts = {parse_response: config.parse_response};
var request_opts = this.get_request_opts(method, uri, config);
var protocol = request_opts.protocol == 'https:' ? https : http;
var request = protocol.request(request_opts, function(response){
var protocol = request_opts.protocol == 'https:' ? https : http;
var request = protocol.request(request_opts, function(response){
if(timer) clearTimeout(timer);
if(timer) clearTimeout(timer);
if((response.statusCode == 301 || response.statusCode == 302) && response.headers.location){
if(count <= config.follow)
return self.send_request(++count, 'GET', response.headers.location, config, null, callback);
else if(config.follow > 0)
return callback(new Error("Too many redirects. Possible redirect loop in " + response.headers.location))
}
if((response.statusCode == 301 || response.statusCode == 302) && response.headers.location){
if(count <= config.follow)
return self.send_request(++count, 'GET', response.headers.location, config, null, callback);
else if(config.follow > 0)
return callback(new Error("Too many redirects. Possible redirect loop in " + response.headers.location))
}
var body = '';
var compressed = /gzip|deflate/.test(response.headers['content-encoding']);
response.setEncoding(compressed ? 'binary' : 'utf8');
var body = '';
var compressed = /gzip|deflate/.test(response.headers['content-encoding']);
response.setEncoding(compressed ? 'binary' : 'utf8');
response.on('data', function(chunk){
body += chunk;
});
response.on('data', function(chunk){
body += chunk;
});
response.on('end', function(){
if(typeof unzip != 'undefined' && compressed)
unzip(new Buffer(body, 'binary'), function(err, buff){
self.response_end(response_opts, response, buff.toString(), callback);
});
else
self.response_end(response_opts, response, body, callback);
response.on('end', function(){
if(typeof unzip != 'undefined' && compressed)
unzip(new Buffer(body, 'binary'), function(err, buff){
self.response_end(response_opts, response, buff.toString(), callback);
});
else
self.response_end(response_opts, response, body, callback);
});
});
});
});
if(config.timeout > 0) {
timer = setTimeout(function() {
request.abort();
}, config.timeout)
}
if(config.timeout > 0) {
timer = setTimeout(function() {
request.abort();
}, config.timeout)
}
request.on('error', function(err) {
if(process.env.DEBUG) console.log('Error on request: ' + err.toString());
if(timer) clearTimeout(timer);
if(callback) callback(err || new Error("Unkown error on request."));
});
request.on('error', function(err) {
if(process.env.DEBUG) console.log('Error on request: ' + err.toString());
if(timer) clearTimeout(timer);
if(callback) callback(err || new Error("Unkown error on request."));
});
if(post_data) request.write(post_data, config.encoding);
request.end();
if(post_data) request.write(post_data, config.encoding);
request.end();
},
},
response_end: function(opts, response, body, callback){
response_end: function(opts, response, body, callback){
if(process.env.DEBUG) console.log(response.headers);
if(!callback) return;
var content_type = response.headers['content-type'] && response.headers['content-type'].split(';')[0];
if(process.env.DEBUG) console.log(response.headers);
if(!callback) return;
var content_type = response.headers['content-type'] && response.headers['content-type'].split(';')[0];
if(opts.parse_response && parsers[content_type]) {
parsers[content_type](body, function(result){
callback(null, response, result);
});
} else {
callback(null, response, body);
}
if(opts.parse_response && parsers[content_type]) {
parsers[content_type](body, function(result){
callback(null, response, result);
});
} else {
callback(null, response, body);
}
},
},
build_multipart_body: function(data, boundary, callback){
build_multipart_body: function(data, boundary, callback){
var body = '';
var object = flatten(data);
var count = Object.keys(object).length;
var body = '';
var object = flatten(data);
var count = Object.keys(object).length;
for(var key in object){
for(var key in object){
var value = object[key];
if(value === null || typeof value == 'undefined') return --count;
var value = object[key];
if(value === null || typeof value == 'undefined') return --count;
var part = (value.buffer || value.file) && value.content_type ? value : {value: value};
var part = (value.buffer || value.file) && value.content_type ? value : {value: value};
this.generate_part(key, part, boundary, function(err, section){
if(err) return callback(err);
body += section;
--count || callback(null, body + '--' + boundary + '--');
});
this.generate_part(key, part, boundary, function(err, section){
if(err) return callback(err);
body += section;
--count || callback(null, body + '--' + boundary + '--');
});
}
}
},
},
generate_part: function(name, part, boundary, callback){
generate_part: function(name, part, boundary, callback){
var return_part = '--' + boundary + "\r\n";
return_part += "Content-Disposition: form-data; name=\"" + name + "\"";
var return_part = '--' + boundary + "\r\n";
return_part += "Content-Disposition: form-data; name=\"" + name + "\"";
var append = function(data, filename){
var append = function(data, filename){
if(data){
return_part += "; filename=\"" + encodeURIComponent(filename) + "\"\r\n";
return_part += "Content-Type: " + part.content_type + "\r\n\r\n";
return_part += (part.content_type.indexOf('text') == -1)
? data.toString('binary')
: data.toString('utf8');
}
if(data){
return_part += "; filename=\"" + encodeURIComponent(filename) + "\"\r\n";
return_part += "Content-Type: " + part.content_type + "\r\n\r\n";
return_part += (part.content_type.indexOf('text') == -1)
? data.toString('binary')
: data.toString('utf8');
}
callback(null, return_part + '\r\n');
};
callback(null, return_part + '\r\n');
};
if((part.file || part.buffer) && part.content_type){
if((part.file || part.buffer) && part.content_type){
var filename = part.filename ? part.filename : part.file ? path.basename(part.file) : name;
if(part.buffer) return append(part.buffer, filename);
var filename = part.filename ? part.filename : part.file ? path.basename(part.file) : name;
if(part.buffer) return append(part.buffer, filename);
fs.readFile(part.file, function(err, data){
fs.readFile(part.file, function(err, data){
if(err) return callback(err);
append(data, filename);
if(err) return callback(err);
append(data, filename);
});
});
} else {
} else {
return_part += "\r\n\r\n";
return_part += part.value;
append();
return_part += "\r\n\r\n";
return_part += part.value;
append();
}
}
}
}

@@ -290,21 +290,21 @@ }

exports.head = function(uri, options, callback){
return Needle.request(uri, 'HEAD', null, options, callback);
return Needle.request(uri, 'HEAD', null, options, callback);
}
exports.get = function(uri, options, callback){
return Needle.request(uri, 'GET', null, options, callback);
return Needle.request(uri, 'GET', null, options, callback);
}
exports.post = function(uri, data, options, callback){
if(!data) throw('POST request expects data.');
return Needle.request(uri, 'POST', data, options, callback);
if(!data) throw('POST request expects data.');
return Needle.request(uri, 'POST', data, options, callback);
}
exports.put = function(uri, data, options, callback){
if(!data) throw('PUT request expects data.');
return Needle.request(uri, 'PUT', data, options, callback);
if(!data) throw('PUT request expects data.');
return Needle.request(uri, 'PUT', data, options, callback);
}
exports.delete = function(uri, data, options, callback){
return Needle.request(uri, 'DELETE', null, options, callback);
return Needle.request(uri, 'DELETE', null, options, callback);
}
{
"name": "needle"
, "version": "0.2.9"
, "version": "0.3.0"
, "description": "Tiny yet feature-packed HTTP client. With deflate & multipart support."

@@ -15,3 +15,3 @@ , "keywords": ["http", "https", "client", "multipart", "deflate", "timeout", "basic-auth", "simple"]

, "bin": {"needle": "./bin/needle"}
, "engines": { "node": ">= 0.4.x < 0.7.0" }
, "engines": { "node": ">= 0.4.x" }
}
Needle
======
Async HTTP client for Node.js. Supports SSL, basic authentication, proxied
requests, multipart form POSTs, gzip/deflate compression and redirect following.
The most handsome HTTP client in the Nodelands. Supports SSL, basic authentication, proxied
requests, multipart form POSTs, gzip/deflate compression and, as you would expect, follows
redirects. Simple, nimble and to the point.

@@ -28,4 +29,4 @@ Usage

- `follow`: Whether to follow redirects or not. Can be a number (of max redirects), `false` or `true` (default, which translates to 10).
- `timeout`: Returns error if response takes more than X. Defaults to `10000` (10 secs). Set to 0 for no timeout.
- `timeout`: Returns error if response takes more than X milisecs. Defaults to `10000` (10 secs). `0` means no timeout.
- `follow`: When `false`, Needle won't follow redirects. Can also be a number or `true` (the default, 10 max).
- `compressed`: Whether to ask for a deflated or gzipped response or not. Defaults to `false`.

@@ -32,0 +33,0 @@ - `parse`: Whether to parse XML or JSON response bodies automagically. Defaults to `true`.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc