Socket
Socket
Sign inDemoInstall

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.0 to 0.2.2

168

lib/needle.js

@@ -17,2 +17,3 @@ //////////////////////////////////////////

http.globalAgent.maxSockets = 128;
exports.version = version;

@@ -47,3 +48,2 @@ try { var unzip = require('zlib').unzip; } catch(e){ /* zlib not supported */ }

// utility function for flattening params in multipart POST's
function flatten(object, into, prefix){

@@ -57,3 +57,3 @@

if(prop && typeof prop === "object" && !(prop.file && prop.content_type))
if(prop && typeof prop === "object" && !((prop.buffer || prop.file) && prop.content_type))
flatten(prop, into, prefix_key)

@@ -75,3 +75,3 @@ else

// normalize arguments
var self = this;
var callback = (typeof options == 'function') ? options : callback;

@@ -84,9 +84,11 @@ var options = options || {};

var port = remote.port || (is_https ? 443 : 80);
var protocol = is_https ? https : http;
var request_compressed = (options.compressed && typeof unzip != 'undefined') || false;
var request_encoding = options.multipart ? 'binary' : 'utf8';
var post_data = null;
var parse_response = options.parse === false ? false : true;
var timeout = options.timeout || 10000; // 10 seconds timeout
var timer = null;
var request_opts = {
encoding: options.multipart ? 'binary' : 'utf8',
protocol: is_https ? https : http,
parse_response: options.parse === false ? false : true,
timeout: options.timeout || 10000 // 10 seconds timeout
}

@@ -102,15 +104,2 @@ var headers = {

if(data) {
if(options.multipart){
var boundary = options.boundary || this.default_boundary;
var post_data = this.build_multipart_body(data, boundary);
headers['Content-Type'] = 'multipart/form-data; boundary=' + boundary;
} else {
var post_data = (typeof(data) === "string") ? data : stringify(data);
headers['Content-Type'] = 'application/x-www-form-urlencoded'
}
headers['Content-Length'] = post_data.length;
// if(process.env.DEBUG) console.log(post_data);
}
for(h in options.headers)

@@ -124,36 +113,49 @@ headers[h] = options.headers[h];

var response_end = function(response, body){
var http_opts = {
host: remote.hostname,
port: port,
path: options.proxy ? uri : remote.pathname + (remote.search || ''),
method: method,
headers: headers,
agent: options.agent || http.globalAgent
}
if(process.env.DEBUG) console.log(response.headers);
var content_type = response.headers['content-type'] && response.headers['content-type'].split(';')[0];
if(data) {
if(options.multipart){
if(parse_response && parsers[content_type]) {
parsers[content_type](body, function(result){
if(callback) callback(null, response, result);
var boundary = options.boundary || this.default_boundary;
return this.build_multipart_body(data, boundary, function(err, body){
if(err) throw(err);
headers['Content-Type'] = 'multipart/form-data; boundary=' + boundary;
headers['Content-Length'] = body.length;
self.send_request(request_opts, http_opts, body, callback);
});
} else {
if(callback) callback(null, response, body);
post_data = (typeof(data) === "string") ? data : stringify(data);
headers['Content-Type'] = 'application/x-www-form-urlencoded';
headers['Content-Length'] = post_data.length;
}
};
var request_opts = {
host: remote.hostname,
port: port,
path: options.proxy ? uri : remote.pathname + (remote.search || ""),
method: method,
headers: headers
}
if(process.env.DEBUG) console.log(request_opts);
this.send_request(request_opts, http_opts, post_data, callback);
var request = protocol.request(request_opts, function(response){
},
send_request: function(request_opts, http_opts, post_data, callback){
if(process.env.DEBUG) console.log(http_opts + "\n\n" + post_data);
var self = this, timer, response_opts = {parse_response: request_opts.parse_response};
var request = request_opts.protocol.request(http_opts, function(response){
if(timer) clearTimeout(timer);
var body = '';
var compressed = /gzip|deflate/.test(response.headers['content-encoding']);
var response_encoding = compressed ? 'binary' : 'utf8';
response.setEncoding(response_encoding);
response.setEncoding(compressed ? 'binary' : 'utf8');
if(timer) clearTimeout(timer);
response.on('data', function(chunk){

@@ -166,6 +168,6 @@ body += chunk;

unzip(new Buffer(body, 'binary'), function(err, buff){
response_end(response, buff.toString())
self.response_end(response_opts, response, buff.toString(), callback);
});
else
response_end(response, body);
self.response_end(response_opts, response, body, callback);
});

@@ -175,25 +177,39 @@

if(timeout) {
if(request_opts.timeout) {
timer = setTimeout(function() {
request.abort();
}, timeout)
}, request_opts.timeout)
}
request.on('error', function(err) {
if(process.env.DEBUG) console.log('Error on request: ' + err);
if(process.env.DEBUG) console.log('Error on request: ' + err.toString());
if(timer) clearTimeout(timer);
if(callback) callback(err || true);
if(callback) callback(err || new Error("Unkown error on request."));
});
if(post_data) request.write(post_data, request_encoding);
if(post_data) request.write(post_data, request_opts.encoding);
request.end();
return request;
},
response_end: function(opts, response, body, callback){
if(process.env.DEBUG) console.log(response.headers);
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){
if(callback) callback(null, response, result);
});
} else {
if(callback) callback(null, response, body);
}
},
build_multipart_body: function(data, boundary){
build_multipart_body: function(data, boundary, callback){
var body = '';
var object = flatten(data);
var count = Object.keys(object).length;

@@ -203,14 +219,17 @@ for(var key in object){

var value = object[key];
if(value !== null && typeof value != 'undefined'){
var part = value.file && value.content_type ? value : {value: value};
body += this.generate_part(key, part, boundary);
}
if(value === null || typeof value == 'undefined') return --count;
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 + '\r\n' + '--' + boundary + '--');
});
}
return body + '\r\n' + '--' + boundary + '--';
},
generate_part: function(name, part, boundary){
generate_part: function(name, part, boundary, callback){

@@ -220,13 +239,27 @@ var return_part = '--' + boundary + "\r\n";

if(part.file && part.content_type){
var append = function(data, filename){
var filename = path.basename(part.file);
var data = fs.readFileSync(part.file);
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');
}
return_part += "; filename=\"" + 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');
};
if((part.file || part.buffer) && part.content_type){
var 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){
if(err) return callback(err);
append(data, filename);
});
} else {

@@ -236,7 +269,6 @@

return_part += part.value;
append();
}
return return_part + '\r\n';
}

@@ -243,0 +275,0 @@

{
"name": "needle"
, "version": "0.2.0"
, "version": "0.2.2"
, "description": "Tiny yet featureful HTTP client. With deflate & multipart POST support."

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

Needle
======
HTTP client for NodeJS. Supports HTTPS, basic authentication, proxied requests, nested params, multipart
Async HTTP client for NodeJS. Supports HTTPS, basic authentication, proxied requests, multipart
form uploads and gzip/deflate compression. Really simple stuff, around ~250 lines of code.

@@ -17,15 +17,16 @@

client.delete(url, [options], callback);
callback receives three arguments: (error, response, body)
```
Callback receives three arguments: (error, response, body)
Options
------
- `timeout`: Returns error if response takes more than X. Defaults to `10000` (10 secs).
- `compressed`: Whether to ask for a deflated or gzipped response or not. Defaults to `false`.
- `timeout`: Returns error if response takes more than X. Defaults to `10000` (10 secs).
- `parse`: Whether to parse XML or JSON response bodies automagically. Defaults to `true`.
- `multipart`: Enables multipart/form-data encoding. Defaults to `false`.
- `username`: For HTTP basic auth.
- `password`: For HTTP basic auth. Requires username to be passed, obviously.
- `parse`: Whether to parse XML or JSON response bodies automagically. Defaults to `true`.
- `agent`: Uses an http.Agent of your choice, instead of the global (default) one.
- `proxy`: Sends request via HTTP proxy. Eg. `proxy: 'http://proxy.server.com:3128'`

@@ -109,3 +110,3 @@

### Multipart POST
### Multipart POST: passing file path

@@ -131,10 +132,27 @@ ``` js

### Multipart POST 2: passing data buffer
``` js
var buffer = fs.readFileSync('/path/to/package.zip');
var data = {
zip_file: { buffer: buffer, filename: 'mypackage.zip', content_type: 'application/octet-stream' },
}
client.post('http://somewhere.com/over/the/rainbow', data, {multipart: true}, function(err, resp, body){
// if you see, when using buffers we need to pass the filename for the multipart body.
// you can also pass a filename when using the file path method, in case you want to override
// the default filename.
});
```
Credits
-------
Written by Tomás Pollak.
Written by Tomás Pollak, with the help of contributors.
Legal
Copyright
-----
(c) Copyright 2011 Fork Ltd. Licensed under the MIT license.
(c) 2012 Fork Ltd. Licensed under the MIT license.

@@ -45,2 +45,4 @@ // TODO: write specs. :)

var black_pixel = new Buffer("data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=".replace(/^data:image\/\w+;base64,/, ""), "base64");
var data = {

@@ -54,3 +56,4 @@ foo: 'bar',

}
}
},
pixel: { filename:'black_pixel.gif', buffer: black_pixel, content_type: 'image/gif' },
}

@@ -84,4 +87,5 @@

multipart_post();
break;
default:
console.log("Usage: ./test.js [get|auth|proxy|multipart]")
}
}

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