npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

teh

v1.0.1

Published

make streaming http requests

Downloads

1

Readme

teh a.k.a hyperquest

treat http requests as a streaming transport

build status

The hyperquest api is a subset of request.

This module works in the browser with browserify.

rant

animated gif rant

This module disables a lot of infuriating things about core http that WILL cause bugs in your application if you think of http as just another kind of stream:

  • http requests have a default idle timeout of 2 minutes. This is terrible if you just want to pipe together a bunch of persistent backend processes over http.

  • There is a default connection pool of 5 requests. If you have 5 or more extant http requests, any additional requests will HANG for NO GOOD REASON.

hyperquest turns these annoyances off so you can just pretend that core http is just a fancier version of tcp and not the horrible monstrosity that it actually is.

I have it on good authority that these annoyances will be fixed in node 0.12.

example

simple streaming GET

var hyperquest = require('hyperquest');
hyperquest('http://localhost:8000').pipe(process.stdout);
$ node example/req.js
beep boop

pooling is evil

Now to drive the point home about pooling being evil and almost always never what you want ever.

request has its own forever agent thing that works pretty much the same as node core http.request: the wrong, horrible, broken way.

For instance, the following request code takes 12+ seconds to finish:

var http = require('http');
var request = require('request');

var server = http.createServer(function (req, res) {
    res.write(req.url.slice(1) + '\n');
    setTimeout(res.end.bind(res), 3000);
});

server.listen(5000, function () {
    var pending = 20;
    for (var i = 0; i < 20; i++) {
        var r = request('http://localhost:5000/' + i);
        r.pipe(process.stdout, { end: false });
        r.on('end', function () {
            if (--pending === 0) server.close();
        });
    }
});

process.stdout.setMaxListeners(0); // turn off annoying warnings
substack : example $ time node many_request.js 
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

real    0m12.423s
user    0m0.424s
sys 0m0.048s

Surprising? YES. This is pretty much never what you want, particularly if you have a lot of streaming http API endpoints. Your code will just HANG once the connection pool fills up and it won't start working again until some connections die for whatever reason. I have encountered this so many times in production instances and it is SO hard to track down reliably.

Compare to using hyperquest, which is exactly the same code but it takes 3 seconds instead of 12 to finish because it's not completely self-crippled like request and core http.request.

var http = require('http');
var hyperquest = require('hyperquest');

var server = http.createServer(function (req, res) {
    res.write(req.url.slice(1) + '\n');
    setTimeout(res.end.bind(res), 3000);
});

server.listen(5000, function () {
    var pending = 20;
    for (var i = 0; i < 20; i++) {
        var r = hyperquest('http://localhost:5000/' + i);
        r.pipe(process.stdout, { end: false });
        r.on('end', function () {
            if (--pending === 0) server.close();
        });
    }
});

process.stdout.setMaxListeners(0); // turn off annoying warnings
$ time node many_hyperquest.js 
0
1
2
3
4
5
6
8
9
7
10
11
12
13
14
15
16
17
18
19

real    0m3.284s
user    0m0.288s
sys 0m0.060s

So the other thing is, the justification I've heard supporting this horrible limit-of-5 pooling behavior is "performance". The first example which has been tuned for "performance" takes 12 seconds. The second example that removes these "performance" enhancements takes 3. Some performance improvement INDEED!

methods

var hyperquest = require('hyperquest');

var req = hyperquest(uri, opts={}, cb)

Create an outgoing http request to uri or opts.uri. You need not pass any arguments here since there are setter methods documented below.

Return a readable or duplex stream depending on the opts.method.

Default option values:

  • opts.method - "GET"
  • opts.headers - {}
  • opts.auth - undefined, but is set automatically when the uri has an auth string in it such as "http://user:passwd@host". opts.auth is of the form "user:pass", just like http.request().
  • opts.agent - false
  • opts.timeout - Math.pow(2, 32) * 1000 The value is passed as an argument to the underlying req.setTimeout() function.
  • opts.localAddress - local interface to bind for network connections (Node.js only)

In https mode, you can specify options to the underlying tls.connect() call:

  • opts.pfx
  • opts.key
  • opts.cert
  • opts.ca
  • opts.ciphers
  • opts.rejectUnauthorized
  • opts.secureProtocol

The request does not go through until the nextTick so you can set values outside of the opts so long as they are called on the same tick.

Optionally you can pass a cb(err, res) to set up listeners for 'error' and 'response' events in one place.

Note that the optional cb is NOT like request in that hyperquest will not buffer content for you or decode to json or any such magical thing.

req.setHeader(key, value);

Set an outgoing header key to value.

req.setLocation(uri);

Set the location if you didn't specify it in the hyperquest() call.

var req = hyperquest.get(uri, opts, cb)

Return a readable stream from hyperquest(..., { method: 'GET' }).

var req = hyperquest.put(uri, opts, cb)

Return a duplex stream from hyperquest(..., { method: 'PUT' }).

var req = hyperquest.post(uri, opts, cb)

Return a duplex stream from hyperquest(..., { method: 'POST' }).

var req = hyperquest.delete(uri, opts, cb)

Return a readable stream from hyperquest(..., { method: 'DELETE' }).

events

req.on('request', function (req) {})

The 'request' event is fired with the ClientRequest object created as a result of the underlying http.request() call.

req.on('response', function (res) {})

The 'response' event is forwarded from the underlying http.request().

req.on('error', function (res) {})

The 'error' event is forwarded from the underlying http.request().

install

With npm do:

npm install hyperquest

license

MIT