SkillAgentSearch skills...

Needle

Nimble, streamable HTTP client for Node.js. With proxy, iconv, cookie, deflate & multipart support.

Install / Use

/learn @tomas/Needle
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Needle

NPM<br />

<!--[![npm version](https://img.shields.io/npm/v/needle.svg?style=flat-square)](https://www.npmjs.org/package/needle)-->

npm downloads Build status

The leanest and most handsome HTTP client in the Nodelands.

var needle = require('needle');

needle.get('http://www.google.com', function(error, response) {
  if (!error && response.statusCode == 200)
    console.log(response.body);
});

Callbacks not floating your boat? Needle got your back.

var data = {
  file: '/home/johnlennon/walrus.png',
  content_type: 'image/png'
};

// the callback is optional, and needle returns a `readableStream` object
// that triggers a 'done' event when the request/response process is complete.
needle
  .post('https://my.server.com/foo', data, { multipart: true })
  .on('readable', function() { /* eat your chunks */ })
  .on('done', function(err) {
    console.log('Ready-o!');
  })

From version 2.0.x up, Promises are also supported. Just call needle() directly and you'll get a native Promise object.

needle('put', 'https://hacking.the.gibson/login', { password: 'god' }, { json: true })
  .then(function(response) {
    return doSomethingWith(response)
  })
  .catch(function(err) {
    console.log('Call the locksmith!')
  })

With only two real dependencies, Needle supports:

  • HTTP/HTTPS requests, with the usual verbs you would expect
  • All of Node's native TLS options, such as 'rejectUnauthorized' (see below)
  • Basic & Digest authentication with auto-detection
  • Multipart form-data (e.g. file uploads)
  • HTTP Proxy forwarding, optionally with authentication
  • Streaming gzip, deflate, and brotli decompression
  • Automatic XML & JSON parsing
  • 301/302/303 redirect following, with fine-grained tuning, and
  • Streaming non-UTF-8 charset decoding, via iconv-lite
  • Aborting any or all Needle requests using AbortSignal objects

And yes, Mr. Wayne, it does come in black.

This makes Needle an ideal alternative for performing quick HTTP requests in Node, either for API interaction, downloading or uploading streams of data, and so on.

Install

$ npm install needle

Usage

// using promises
needle('get', 'https://server.com/posts/123')
  .then(function(resp) {
    // ...
  })
  .catch(function(err) {
    // ...
  });

// with callback
needle.get('ifconfig.me/all.json', function(error, response, body) {
  if (error) throw error;

  // body is an alias for `response.body`,
  // that in this case holds a JSON-decoded object.
  console.log(body.ip_addr);
});

// no callback, using streams
needle.get('https://google.com/images/logo.png')
  .pipe(fs.createWriteStream('logo.png'))
  .on('done', function(err) {
    console.log('Pipe finished!');
  });

As you can see, you can use Needle with Promises or without them. When using Promises or when a callback is passed, the response's body will be buffered and written to response.body, and the callback will be fired when all of the data has been collected and processed (e.g. decompressed, decoded and/or parsed).

When no callback is passed, however, the buffering logic will be skipped but the response stream will still go through Needle's processing pipeline, so you get all the benefits of post-processing while keeping the streamishness we all love from Node.

Response pipeline

Depending on the response's Content-Type, Needle will either attempt to parse JSON or XML streams, or, if a text response was received, will ensure that the final encoding you get is UTF-8.

You can also request a gzip/deflated/brotli response, which, if sent by the server, will be processed before parsing or decoding is performed. (Note: brotli is only supported on Node 10.16.0 or above, and will not be requested or processed on earlier versions.)

needle.get('http://stackoverflow.com/feeds', { compressed: true }, function(err, resp) {
  console.log(resp.body); // this little guy won't be a Gzipped binary blob
                          // but a nice object containing all the latest entries
});

Or in anti-callback mode, using a few other options:

var options = {
  compressed         : true, // sets 'Accept-Encoding' to 'gzip, deflate, br'
  follow_max         : 5,    // follow up to five redirects
  rejectUnauthorized : true  // verify SSL certificate
}

var stream = needle.get('https://backend.server.com/everything.html', options);

// read the chunks from the 'readable' event, so the stream gets consumed.
stream.on('readable', function() {
  while (data = this.read()) {
    console.log(data.toString());
  }
})

stream.on('done', function(err) {
  // if our request had an error, our 'done' event will tell us.
  if (!err) console.log('Great success!');
})

API

needle(method, url[, data][, options][, callback]) (> 2.0.x)

Calling needle() directly returns a Promise. Besides method and url, all parameters are optional, although when sending a post, put or patch request you will get an error if data is not present.

needle('get', 'http://some.url.com')
  .then(function(resp) { console.log(resp.body) })
  .catch(function(err) { console.error(err) })

Except from the above, all of Needle's request methods return a Readable stream, and both options and callback are optional. If passed, the callback will return three arguments: error, response and body, which is basically an alias for response.body.

needle.head(url[, options][, callback])

needle.head('https://my.backend.server.com', {
  open_timeout: 5000 // if we're not able to open a connection in 5 seconds, boom.
}, function(err, resp) {
  if (err)
    console.log('Shoot! Something is wrong: ' + err.message)
  else
    console.log('Yup, still alive.')
})

needle.get(url[, options][, callback])

needle.get('google.com/search?q=syd+barrett', function(err, resp) {
  // if no http:// is found, Needle will automagically prepend it.
});

needle.post(url, data[, options][, callback])

var options = {
  headers: { 'X-Custom-Header': 'Bumbaway atuna' }
}

needle.post('https://my.app.com/endpoint', 'foo=bar', options, function(err, resp) {
  // you can pass params as a string or as an object.
});

needle.put(url, data[, options][, callback])

var nested = {
  params: {
    are: {
      also: 'supported'
    }
  }
}

needle.put('https://api.app.com/v2', nested, function(err, resp) {
  console.log('Got ' + resp.bytes + ' bytes.') // another nice treat from this handsome fella.
});

needle.patch(url, data[, options][, callback])

Same behaviour as PUT.

needle.delete(url, data[, options][, callback])

var options = {
  username: 'fidelio',
  password: 'x'
}

needle.delete('https://api.app.com/messages/123', null, options, function(err, resp) {
  // in this case, data may be null, but you need to explicity pass it.
});

needle.request(method, url, data[, options][, callback])

Generic request. This not only allows for flexibility, but also lets you perform a GET request with data, in which case will be appended to the request as a query string, unless you pass a json: true option (read below).

var params = {
  q    : 'a very smart query',
  page : 2
}

needle.request('get', 'forum.com/search', params, function(err, resp) {
  if (!err && resp.statusCode == 200)
    console.log(resp.body); // here you go, mister.
});

Now, if you set pass json: true among the options, Needle won't set your params as a querystring but instead send a JSON representation of your data through the request's body, as well as set the Content-Type and Accept headers to application/json.

needle.request('get', 'forum.com/search', params, { json: true }, function(err, resp) {
  if (resp.statusCode == 200) console.log('It worked!');
});

Events

The Readable stream object returned by the above request methods emits the following events, in addition to the regular ones (e.g. end, close, data, pipe, readable).

Event: 'response'

  • response <http.IncomingMessage>

Emitted when the underlying http.ClientRequest emits a response event. This is after the connection is established and the header received, but before any of it is processed (e.g. authorization required or redirect to be followed). No data has been consumed at this point.

Event: 'redirect'

  • location <String>

Indicates that the a redirect is being followed. This means that the response code was a redirect (301, 302, 303, 307) and the given redirect options allowed following the URL received in the Location header.

Event: 'header'

  • statusCode <Integer>
  • headers <Object>

Triggered after the header has been processed, and just before the data is to be consumed. This implies that no redirect was followed and/or authentication header was received. In other words, we got a "valid" response.

Event: 'done' (previously 'end')

  • exception <Error> (optional)

Emitted when the request/response process has finished, either because all data was consumed or an error ocurred somewhere in between. Unlike a regular stream's end event, Needle's done will be fired either on success or on failure, which is why the first argument may be an Error object. In other words:

var resp = needle.get('something.worthy/of/being/streamed/by/needle');
resp.pipe(someWritableStream);

resp.on('done', function(err) {
  if (err) console.log('An error ocurred: ' + err.message);
  else console.log('Great success!');
})

E

View on GitHub
GitHub Stars1.6k
CategoryCustomer
Updated2d ago
Forks238

Languages

JavaScript

Security Score

95/100

Audited on Mar 28, 2026

No findings